MS leetcode 题目

# 717 1比特与2比特字符:判断末尾符号是哪一种

思路:线性从前向后遍历,维护一个映射list。

class Solution:
    def isOneBitCharacter(self, bits: List[int]) -> bool:
        if len(bits)==1:
            return True
        else:
            mapList=[]
            while len(bits)>0:
                if bits[0]==1:
                    mapList.append('F')
                    bits.pop(0)
                    bits.pop(0)
                else:
                    mapList.append('T')
                    bits.pop(0)
            if mapList[-1]=='T':
                return True
            else:
                return False
View Code

# 67 二进制求和:二进制加法

思路:首先处理字符串长度不一致的问题,为较短的字符串前面添0,将两个字符串补齐。然后从后往前加即可,当前位置上的两个数+进位。

class Solution:

    def addZero(self,a,b):
        diff=abs(len(b)-len(a))
        if len(a)<len(b):
            a='0'*diff+a
        elif len(a)>len(b):
            b = '0' * diff + b
        return a,b

    def addBinary(self, a: str, b: str) -> str:
            result=''
            a,b=self.addZero(a,b)
            flag=0 # 进位
            for i in range(len(a)):
                tmp=int(a[len(a)-i-1])+int(b[len(b)-i-1])+flag
                if tmp==2:
                    flag=1
                    result+='0'
                elif tmp==3:
                    flag = 1
                    result += '1'
                else:
                    flag=0
                    result += str(tmp)
            if flag==1:
                result += '1'
            back=''.join(list(reversed(result)))
            return back
View Code

 # 415: 67的升级版, replace if-else with //(整除) and %(取余)

class Solution:
    def addZero(self,a,b):
        diff=abs(len(b)-len(a))
        if len(a)<len(b):
            a='0'*diff+a
        elif len(a)>len(b):
            b = '0' * diff + b
        return a,b

    def addStrings(self, num1: str, num2: str) -> str:
        result=''
        a,b=self.addZero(num1,num2)
        flag=0 # 进位
        for i in range(len(a)):
            tmp=int(a[len(a)-i-1])+int(b[len(b)-i-1])+flag
            result+=str(tmp%10) # 10进制数
            flag=tmp//10 
        if flag!=0: #由于题目要求字符串前面不能有0,所以只有非0才添加
            result += str(flag)
        back=''.join(list(reversed(result)))
        return back
View Code

 ### 从这道题开始,我就不按照LC官网类的方式记录了,直接贴函数代码>>_<<

# 107: DFS+维护一个以深度为key的字典, value是一个list, 在DFS时依次append, 最后按照key从大到小返回对应value(主要难点在于DFS的实现,DFS的实现方式主要有两种,一种是递归,一种是栈,这里采用递归的实现方式)

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def DFS(root,depth,depthDict):
    if root!=None:
        if depth not in depthDict.keys():
            depthDict[depth]=[]
            depthDict[depth].append(root.val)
        else:
            depthDict[depth].append(root.val)
        DFS(root.left,depth+1,depthDict)
        DFS(root.right, depth+1, depthDict)
    else:
        return

def levelOrderBottom(root): # root: TreeNode
    res=[]
    depthDict={}
    depth=0
    DFS(root,depth,depthDict)
    keysSort=list(reversed(sorted(list(depthDict.keys()))))
    for i in keysSort:
        res.append(depthDict[i])
    return res

# Test sample
rr=TreeNode(3)
rr.left=TreeNode(9)
rr.right=TreeNode(20)
rr.right.left=TreeNode(15)
rr.right.right=TreeNode(7)
print(levelOrderBottom(rr))
View Code

 # 257: DFS (这两道二叉树的题目做起来都有点困难,可能因为对递归理解还不是非常透彻,这里关键在于递归的过程中path会被自动维护)

# Use the definition for a binary tree node in 107.
def binaryTreePaths(root): # List[str]
    Paths=[]
    Path=''

    def DFS_257(root, path):
        if root != None:
            if path == '':
                path += str(root.val)
            else:
                path += ('->' + str(root.val))
            if root.left==None and root.right==None:
                Paths.append(path)
            DFS_257(root.left, path)
            DFS_257(root.right, path)
        else:
            return

    DFS_257(root,Path)
    return Paths

# Test sample
# rr=TreeNode(3)
# rr.left=TreeNode(9)
# rr.right=TreeNode(20)
# rr.right.left=TreeNode(15)
# rr.right.right=TreeNode(7)
# print(binaryTreePaths(rr))
View Code

 这里补充一下递归分析:

 # 70: DP (乍一看以为这道题就是求二叉树的路径条数,以为可以使用DFS,然递归DFS超时==), 用DP的话首先需要写出通项公式,这里假设f(x)是爬x阶楼梯的方案数,而最后一步可以走1步或者2步,我们可以得到f(x)=f(x-1)+f(x-2),这个比较难想,竟然是斐波那契数。

def climbStairs(n): # DP
    l=0
    r=1
    sum=0
    for i in range(n):
        sum=l+r
        l=r
        r=sum
    return r
View Code

(有关通项的理解后续再补充)

 # 30: 外观数列, 这道题的解法写的比较任意,就是线性扫描+集合判断,更加规范的应该用双指针。

线性扫描+集合

def count(num):
    str_num=str(num)
    descriptor=''
    filter_set=[]
    for i in str_num:
        filter_set.append(i)
        if len(set(filter_set))==2:
            descriptor+=(str(len(filter_set[:-1]))+filter_set[-2])
            filter_set = [filter_set[-1]]
        else:
            continue
    descriptor+=(str(len(filter_set))+str(filter_set[-1]))
    return int(descriptor)

def countAndSay(n):
    res=1
    for i in range(n-1):
        res=count(res)
    return str(res)

print(countAndSay(5))
View Code

 # 204 数质数,该题用常规方法去判断会超时,尝试加了很多trick还是会超时,最后参考了其他人的题解,采用了埃氏筛的方法,主要是对该方法的理解(算法实现)。

def countPrimes(n): # 埃氏筛
    isPrime=[1]*n # 初始化很重要
    cnt=0
    for i in range(2,n):
        if isPrime[i]:
            cnt+=1
        for j in range(i*i,n,i):
            isPrime[j]=0
    return cnt
View Code

 # 706 自己实现一个hash表,也就是python中的字典。解决两个问题,第一,哈希函数,第二,哈希碰撞。1,采用取模长%len;2,用一个数组把映射在同一位置的元素装起来,所以是两个数组的嵌套。(这里将第一个数组的长度设置为2069,参考解答的设置,any质数都可以,减小碰撞概率而已)

class MyHashMap:

    def __init__(self):
        self.map=[[]]*2069 # 2069 as a prime

    def put(self, key: int, value: int) -> None:
        index=key%2069
        for lst in self.map[index]:
            if lst[0]==key:
                lst[1]=value
                return None
        self.map[index].append([key,value])

    def get(self, key: int) -> int:
        index=key%2069
        for lst in self.map[index]:
            if lst[0]==key:
                return lst[1]
        return -1

    def remove(self, key: int) -> None:
        index = key % 2069
        for i in range(len(self.map[index])):
            if self.map[index][i][0] == key:
                del self.map[index][i]
                break # 要加break,不然会有错,因为这种for iterator删除当前元素继续访问会造成冲突
View Code

 # 509 斐波那契数(70题的本质)

def fib(n):
    if n==0:
        return 0
    else:
        l = 0
        r = 1
        sum = 0
        for i in range(n - 1):
            sum = l + r
            l = r
            r = sum
        return r
View Code

# 724 找中心索引使得左右两边和相等, 题目也比较好理解,我直接用了sum函数判断,发现两个有意思的点: sum([])=0 ; list[:0]=[] list[len(list):]=[] 第二个点说明切片不会造成越界问题,比如这样:

def pivotIndex(nums):
    for i in range(len(nums)):
        if sum(nums[:i])==sum(nums[(i+1):]):
            return i
    return -1
View Code

 # 387 字符串中的唯一字符,该题目比较简单,不多分析,就用字典存储频数即可。

def firstUniqChar(s):
    uniqueCharList=[]
    times={}
    for i in s:
        if i not in uniqueCharList:
            uniqueCharList.append(i)
            times[i]=1
        else:
            times[i]+=1
    print(uniqueCharList)
    print(times)
    for key in times.keys():
        if times[key]==1:
            return s.index(key)
    return -1
View Code

# 198: 数组中不相邻元素的最大和,使用动态规划,经典步骤,建立函数关系f(x),写出子结构表达式。本题目分析如下 (代码部分参考精选题解):

def rob(nums):
    if len(nums)==0:
        return 0
    elif len(nums)==1:
        return nums[0]
    else:
        N=len(nums)
        dp=[0]*(N+1)
        dp[0]=0
        dp[1]=nums[0]
        for i in range(2,N+1):
            dp[i]=max(dp[i-1],dp[i-2]+nums[i-1])
        return dp[N]
View Code

 # 232 用两个栈模拟队列,一个栈作为输入栈,一个栈作为输出栈,push的时候都加入输入栈,pop从输出栈弹出,此时如果为空就需要将输入栈的全部弹出到输出栈再输出。(相当于将一个队列拆成了两部分,入栈和出栈)

这个video很清晰==

class MyQueue:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.inputStack=[]
        self.outputStack=[]


    def push(self, x: int) -> None:
        """
        Push element x to the back of queue.
        """
        self.inputStack.append(x)


    def pop(self) -> int:
        """
        Removes the element from in front of queue and returns that element.
        """
        if len(self.outputStack)!=0:
            value=self.outputStack.pop()
            return value
        else:
            for i in range(len(self.inputStack)):
                self.outputStack.append(self.inputStack.pop())
            value = self.outputStack.pop()
            return value


    def peek(self) -> int:
        """
        Get the front element.
        """
        if len(self.outputStack)!=0:
            value=self.outputStack[-1]
            return value
        else:
            for i in range(len(self.inputStack)):
                self.outputStack.append(self.inputStack.pop())
            value = self.outputStack[-1]
            return value


    def empty(self) -> bool:
        """
        Returns whether the queue is empty.
        """
        if len(self.inputStack)==0 and len(self.outputStack)==0:
            return True
        else:
            return False
View Code

 # 225 用两个队列模拟栈:核心思想就是将一个队列辅以某些操作直接变成栈的存储结构(元素取反存储)。实现:一个队列+一个tmp队列

class MyStack:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.Q=[]
        self.Q_tmp=[]

    def push(self, x: int) -> None:
        """
        Push element x onto stack.
        """
        self.Q_tmp=[]
        self.Q_tmp.append(x)
        if len(self.Q)!=0:
            for i in range(len(self.Q)):
                self.Q_tmp.append(self.Q[i])
        self.Q=self.Q_tmp

    def pop(self) -> int:
        """
        Removes the element on top of the stack and returns that element.
        """
        res=self.Q[0]
        self.Q=self.Q[1:]
        return res

    def top(self) -> int:
        """
        Get the top element.
        """
        return self.Q[0]

    def empty(self) -> bool:
        """
        Returns whether the stack is empty.
        """
        if len(self.Q)==0:
            return True
        else:
            return False
View Code

 # 28 查找子字符串出现的位置

def strStr(haystack, needle):
    if needle=='' or needle==haystack:
        return 0
    elif len(needle)>len(haystack):
        return -1
    else: # needle 长度小于hay
        for i in range(len(haystack)):
            if i+len(needle)<=len(haystack):
                if haystack[i:i+len(needle)]==needle:
                    return i
                else:
                    if i + len(needle) == len(haystack): # 考虑最后一次不匹配的情况
                        return -1
                    continue
            else:
                return -1
View Code

写的太复杂了==按照相同的思路可以用一行代码实现(for start in range(n - L + 1):)or 还可以采用基于hash的方法,将字符串映射到hash,如Rabin Karp

 # 349 两个数组的交集(就遍历...)

def intersection(nums1, nums2):
    intersect=[]
    for i in nums1:
        if (i in nums2) and (i not in intersect):
            intersect.append(i)
    return intersect
View Code

# 784 字母大小写全排列。这个题目关键是抓住全排列和二进制数之间的关系。

def letterCasePermutation(S):
    L=[]
    letterIndex=[]
    idx=-1
    str=S # store numbers in S and reserve space for character
    for i in S: # 数字
        idx+=1
        if i>='0' and i<='9':
            L.append(i)
        else: # 字母
            letterIndex.append(idx)
            L.append([i.lower(),i.upper()])
    if len(letterIndex)==0: # 没有字母
        return [S]
    else: # 有字母
        # 全排列等价于二进制数
        sortArray = []
        for i in range(2 ** len(letterIndex)):
            tmp = bin(i)[2:]
            while len(tmp) < len(letterIndex):
                tmp = '0' + tmp
            sortArray.append(tmp)
        res = []
        for sort in sortArray:
            for ith in range(len(sort)):
                str = list(str)
                str[letterIndex[ith]] = L[letterIndex[ith]][int(sort[ith])]
                str = ''.join(str)
            res.append(str)
        return res
View Code

(代码写的太不算法了,完全是拿数学和规律来解==,标准做法应该是构建一棵树,用递归来做)

# 14 最长公共前缀:思路是先选取一个最短的字符串,然后与其他的进行比较,将模板字符串从长到短比较。

def longestCommonPrefix(strs):
    minl=201
    mintemplate=''
    for i in strs: # 取最短的字符串作为模板来匹配其他的
        if len(i)<minl:
            minl=len(i)
            mintemplate=i
    for i in reversed(range(minl)):
        TrueFalseSet=set()
        for j in range(len(strs)):
            TrueFalseSet.add(mintemplate[:i+1]==strs[j][:i+1])
        if len(TrueFalseSet)==1 and list(TrueFalseSet)[0]==True:
            return mintemplate[:i+1]
        else:
            continue
    return ''
View Code

Follow this repo, update this blog continuously. 1.28 暂时停更,准备开始按类型刷。

原文地址:https://www.cnblogs.com/pear-linzhu/p/14242346.html