【Code Practice 1】

Hot 100 leetcode

笔试整理

8.24 贝壳(四道加起来过了...74%...)

1 动态规划

#吃糖题:
n=5
dp=[0]*(n+1)  #记录吃第i颗的最少次数
#dp[i]=min(dp[i],dp[j]+1) if j 到i之间可以一次吃掉
num=[1,1,2,3,4]
if n==1:
    print(1)
else:
    dp=[0]*(n+1)
    for i in range(1,n+1):
        dp[i]=i
        for j in range(i):  #看前面j到i之间的数,是否是2的次方,判断方法不是被2整除!!!
            #正确的判断方法: n&(n-1),把最右面的1消除。如果能被2整除,那么一定只有一个1,所以消除后就是0了
            arr=num[j:i] 
            if sum([2**k for k in arr])&(sum([2**k for k in arr])-1)==0:  
                dp[i]=min(dp[i],dp[j]+1)  #如果可以,说明j到i之间的可以一次吃掉,那么就是第j的次数+1
        dp[i]=min(dp[i],dp[i-1]+1)
    print (dp)

8.24 京东(两道,过了36%)

不难,不要有想法,踏实做吧

#合唱队,给出身高数组,要分组,且满足每组的身高都从小到大递增,并保证分完组整体也满足从小到大递增,
#最多可以分多少组
#看了网上的答案,思路:
#如果i前的最大值,小于或等于i后面的最小值,那么就可以将i前的分为一组(排好序后的最大值小于等后面的最小值)
#一次从前向后遍历,dp_max[i]记录身高中,截止到i目前的最大值,
#一次从后向前遍历,dp_min[i]记录身高中,截止到i的后面最小值是多少。

n=5
num=[2,1,3,2,1]
dp_max=[0]*n
dp_min=[0]*n
maxx=float("-inf")
minn=float("inf")
for i in range(n):
    maxx=max(maxx,num[i])
    dp_max[i]=maxx
for j in range(n-1,-1,-1):
    minn=min(minn,num[i])
    dp_min[i]=minn
for i in range(n-1):
    if dp_max[i]<=dp_minn[i+1]:
        res+=1
print(res)

9.1 腾讯

动态规划(暴力求所有组合过0)

dp[i]表示长度为i时的方案数量=i-k时的方案数(后面k朵全白)+i-1的方案数(最后一朵放红)

dp[i]=dp[i-k]+dp[i-1] , 当i<k时 dp[i-k]=0

翻转二叉树

  ——> 

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return
        leftnode=root.left #先存储左节点
        root.left=self.invertTree(root.right)
        root.right=self.invertTree(leftnode)
        return root

538. 把二叉搜索树转换为累加树

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

class Solution(object):
    def convertBST(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        #二叉搜索树性质:左<中<右
        #中序遍历的反向,先右,然后累加给中,然后累加给左
        if not root:
            return None
        node=root
        stack=[]
        s=0
        while node or stack:
            while node:
                stack.append(node)
                node=node.right
            node=stack.pop()
            s+=node.val  #s是从右边开始,每一步都要累加的。
            node.val=

路径总和 II (广度优先遍历,累计记忆)

class Solution(object):
    def pathSum(self, root, summ):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        #广度优先遍历BFS(记忆每一个路径上的数,累计记忆)
        #新的结构 [(Node,[node1.val,node2.val,...])] #set里面节点与节点前路径上的所有值
        if not root:
            return []
        stack=[(root,[root.val])]
        res=[]
        for i,j in stack:
            if not i.left and not i.right and sum(j)==summ:
                res.append(j)
            if i.left:
                copy_j=j[:]
                copy_j.append(i.left.val)
                stack.append((i.left,copy_j))
            if i.right:
                copy_j=j[:]
                copy_j.append(i.right.val)
                stack.append((i.right,copy_j))
        return res

        """
        #回溯
        res=[]
        def dfs(root,temp,sumnum):
            if not root.left and not root.right and sumnum==root.val:
                temp.append(root.val)
                res.append(temp[:])
                return
            if root.left:
                dfs(root.left,temp+[root.val],sumnum-root.val)
            if root.right:
                dfs(root.right,temp+[root.val],sumnum-root.val)
        if not root:
            return []
        dfs(root,[],summ)
        return res
        """

路径总和 III

class Solution(object):
    def pathSum(self, root, summ):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int
        """
        
        self.count=0
        def dfs(root,temp):
            if not root:
                return
            temp.append(root.val)
            cur=0
            for i in range(len(temp)-1,-1,-1): #从后往前,检查以root.val结尾的解的个数
                cur+=temp[i]
                if cur==summ:
                    self.count+=1
            dfs(root.left,temp)
            dfs(root.right,temp)
            temp.pop() #回溯,还原当前值
        dfs(root,[])
        return self.count
                
        """
        #超时,过了90%,
        def dfs(root,temp,sumnum):
            if not root:
                return
            if sumnum==root.val:
                temp.append(root.val)
                res.append("->".join(str(s) for s in temp[:]))
                #return 
            #if root.left:
            dfs(root.left,temp+[root.val],sumnum-root.val)
            #if root.right:
            dfs(root.right,temp+[root.val],sumnum-root.val)
        if not root:
            return 0
        stack=[root]
        al=[root] #记录所有节点
        res=[] #记录所有路径
        while stack:
            temp=[]
            leng=len(stack)
            for i in range(leng):
                if stack[i].left:
                    temp.append(stack[i].left)
                if stack[i].right:
                    temp.append(stack[i].right)
            stack=temp
            if temp:
                al.extend(temp)
        for node in al:
            dfs(node,[],summ)
        return len(res)
        """

"""
    def pathSum(self, root, summ):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int
        """
        #广度优先遍历,超时
        if not root:
            return 0
        stack=[(root,[root.val])]
        res=[]
        for i,j in stack:
            c=0
            for k in range(len(j)-1,-1,-1):  #以该节点结尾的所有路径
                c+=j[k]
                if c==summ:
                    res.append("->".join(str(s) for s in j[k:]))
            if i.left:
                copy_j=j[:]
                copy_j.append(i.left.val)
                stack.append((i.left,copy_j))
            if i.right:
                copy_j=j[:]
                copy_j.append(i.right.val)
                stack.append((i.right,copy_j))
        return len(res)
"""

5 最小栈

class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack1=[]
        self.stack2=[]

    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        #stack2存储最小值。每次比较新加入的值和栈顶值,添加最小的进栈
        self.stack1.append(x)
        if not self.stack2:
          self.stack2.append(x)
        else:
          temp=self.stack2[-1]
          if x<temp:
            self.stack2.append(x)
          else:
            self.stack2.append(temp)

    def pop(self):
        """
        :rtype: None
        """
        if not self.stack1:
          return "empty error"
        self.stack2.pop() #pop记得将最小值栈也pop
        return self.stack1.pop()
        

    def top(self):
        """
        :rtype: int
        """
        return self.stack1[-1] if self.stack1 else "empty error"

    def getMin(self):
        """
        :rtype: int
        """
        return self.stack2[-1]

二叉树的直径

class Solution(object):
    def diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.max=0
        self.diameter(root)
        return self.max
      
    def diameter(self, root):
        #层次遍历,获得左子树最大深度h1,还有右子树最大深度h2,返回 h1+h2
        #但容易忽略特殊情况,最长路径在一侧,所以是每个节点作为根节点的左右深度和,求最大值
        if not root:
          return
        h1=self.depth(root.left,0)
        h2=self.depth(root.right,0)
        self.max=max(self.max,h1+h2)
        self.diameter(root.left) #左右子树都要递归判断
        self.diameter(root.right)
    
    #层次遍历求深度     
    def depth(self,root,h):
      if root:
        stack=[root]
        while stack:
          leng=len(stack)
          temp=[]
          for i in range(leng):
            if stack[i].left:
              temp.append(stack[i].left)
            if stack[i].right:
              temp.append(stack[i].right)
          h+=1
          stack=temp
      return h
      
    """
        self.max=0
        self.depth(root)
        return self.max
        
    #递归求深度:
    def depth(self,root):
      if not root:
        return 0
      l=self.depth(root.left)
      r=self.depth(root.right)
      self.max=max(self.max,l+r)
      return max(l,r)+1
      
    """ 

回文链表

找到中点->反转后半部分->遍历比较前后两个链表

class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        #找到中点
        fast,slow=head,head
        while fast and fast.next:
            fast=fast.next.next
            slow=slow.next
        #反转后半部分
        mid=slow
        pre=None
        while mid:
            nex=mid.next
            mid.next=pre
            pre=mid
            mid=nex
        #pre是后半部分反转后的头节点
        while pre:
            if pre.val!=head.val: #比较的值是否一样,记得加val!!!
                return False
            pre=pre.next
            head=head.next
        return True

找到字符串中所有字母异位词(滑动窗口思想)

滑动窗口思想:右侧窗口不断右移加入元素,当个数等于p的长度时,判断里面各元素是否相等。若相等:则添加左边index,无论是否相等,到达长度都要左侧右移,更新窗口内的left(windows[s[left]]-=1)。右侧窗口继续右移。

from collections import Counter

d=Counter(s)  直接获得字符串s的统计字符及其个数的字典

    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        #滑动窗口思想
        window={}
        need={}
        for i in p:
          need[i]=need.get(i,0)+1
        res=[]
        l=r=0
        while r<len(s):
          temp=s[r]
          if temp not in need: #不存在与p,则清除窗口
            window={}
            l=r+1
            r=r+1
          else:
            window[temp]=window.get(temp,0)+1
            if r-l+1==len(p):  #若长度达到要求
              if window==need:  #若找到,则加入res,左侧左移,更新窗口值
                res.append(l)
              window[s[l]]-=1  #无论是否找到,都要左移,更新窗口值
              l+=1
            r+=1
        return res
       #方法2,暴力
        """
        #O(len(s)*len(p))超时
        leng=len(p)
        d=Counter(p)
        res=[]
        for k in range(len(s)-leng+1):
          if self.judge(s[k:k+leng],d):
            res.append(k)
          else:
            continue
        return res
    #每次查看是否相等       
    def judge(self,s,d):
      t1=Counter(s)
      for i in d:
        if i not in t1 or t1[i]!=d[i]:
          return False
      return True
        """

无重复字符的最长子串(滑动窗口)

窗口window是字典,记录元素的index位置。右面依次右移,如果遇到重复的,更新长度,找到上一个重复的位置index,将index前的window全部清除(这里直接全部清除),将左侧和右侧重新定位在index+1,:如“tmmxbat”。然后继续右移。

    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        #用切片
        l=[]
        res=[]
        for i in range(len(s)):
            if s[i] not in l:
                l.append(s[i])
                res.append(len(l))
            else:
                index=l.index(s[i])
                l=l[index+1:]  #更新子串,将重复的及之前的清理掉
                l.append(s[i])
        res.append(len(l)) #abbbcdef的情况,最长的在最后
        return max(res)
        
        """
        #滑动窗口
        if not s:
            return 0
        window={} #记录元素的index值
        res=1
        left=right=0
        while right<len(s):
            temp=s[right]
            if temp not in window:  #若窗口内没有重复值
                window[temp]=right #存储index
                res=max(res,right-left+1)  #避免一直没有重复的情况,所以也要更新一下 如abcd
            else:  #窗口内存在重复值
                res=max(res,right-left)  #更新窗口最大长度,该重复值不算,所以窗口长度要-1
                index=window[temp] #找到上一个重复值的位置
                left=right=(index+1)   
                window.clear() #将index前的全部清理,防止后面再次查询到 ,如 "tmmzuxt"
                window[s[left]]=right #将新window的第一个字符加入window
            right+=1
        return res
        """

10 581. 最短无序连续子数组

    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        #两次遍历,左到右,找到右边界(比其左边最大值要小的),右到左,找到左边界(比其右边最小值还要大的)
        L=0
        R=0
        maxx=nums[0]
        minn=nums[-1]
        for i in range(len(nums)):
            if nums[i]<maxx:
                R=i
            maxx=max(maxx,nums[i])
        for j in range(len(nums)-1,-1,-1):
            if nums[j]>minn:
                L=j
            minn=min(minn,nums[j])
        return R-L+1 if R>L else 0  #如果没有乱序的,则L=R=0
        
        """
        #排序后,双指针前后对比
        arr=sorted(nums)
        leng=len(nums)
        i=0
        j=leng-1
        while i<leng and nums[i]==arr[i]:
            i+=1
        while j>=0 and nums[j]==arr[j]:
            j-=1
            
        return j-i+1 if j>i else 0
        """

11 每日温度

    def dailyTemperatures(self, T):
        """
        :type T: List[int]
        :rtype: List[int]
        """
        #记录,后入栈的元素values与栈顶元素s比较:
        #若value>s,则说明栈顶元素s找到了比其大的值,记录下标之差,然后依次出栈
        #若value<=s,则直接入栈,待寻找
        stack=[]
        res=[0]*len(T)
        for i in range(len(T)):
            if stack:
                while stack and T[stack[-1]]<T[i]:
                    res[stack[-1]]=i-stack[-1]
                    stack.pop()
            stack.append(i)
        return res

        
        """
        #暴力,超时
        res=[]
        for i in range(len(T)):
            temp=T[i]
            j=i+1
            while j<len(T) and T[j]<=temp:
                j+=1
            if j==len(T):
                res.append(0)
            else:
                res.append(j-i)
        return res
        """

12 688. “马”在棋盘上的概率(回溯+记忆)

class Solution(object):
    def knightProbability(self, N, K, r, c):
        """
        :type N: int
        :type K: int
        :type r: int
        :type c: int
        :rtype: float
        """
        #三:记忆+回溯,记录已经走过的概率,再碰到就直接返回该点的概率
        mem={}
        
        dic=[[2,1],[2,-1],[1,2],[1,-2],[-2,1],[-2,-1],[-1,2],[-1,-2]]
        def f(x,y,k):
            
            #记忆化搜索
            if (x,y,k) in mem:
                return mem[(x,y,k)]
            
            if k==K:
                return 1
            p=0
            for dx,dy in dic:
                if N>x+dx>=0 and N>y+dy>=0:
                    p+=f(x+dx,y+dy,k+1)
                else:
                    continue
            p/=8.0
            mem[(x,y,k)]=p
            return p
        return f(r,c,0)
        
        """
        #一:层次遍历,最后一层的个数就是所有的路径数
        dic=[[2,1],[2,-1],[1,2],[1,-2],[-2,1],[-2,-1],[-1,2],[-1,-2]]
        count=0
        stack=[[r,c]]
        i=0
        while i<K:
            temp=[]
            for x,y in stack:
                for dx,dy in dic:
                    if N>x+dx>=0 and N>y+dy>=0:
                        temp.append([x+dx,y+dy])
            stack=temp
            i+=1
        count=len(stack)
        return count/float(8**K)
        
        
        #二:暴力回溯方法,超时,11/21
        dic=[[2,1],[2,-1],[1,2],[1,-2],[-2,1],[-2,-1],[-1,2],[-1,-2]]
        self.res=0
        def f(x,y,k):
            if k==K:
                self.res+=1
                return
            for dx,dy in dic:
                if N>x+dx>=0 and N>y+dy>=0:
                    f(x+dx,y+dy,k+1)
                else:
                    continue
        f(r,c,0)
        return self.res/float(8**K)
        """

13 一和零

01背包问题(但是是多维的,不仅满足体积,还要满足质量)

外面物品循环,里面是逆序的质量和体积的双重循环 dp[i][j]=max( dp[i] [j], 1+dp [i-count_0] [j-count_1] ) 

    def findMaxForm(self, strs, m, n):
        """
        :type strs: List[str]
        :type m: int
        :type n: int
        :rtype: int
        """
        numss=[]
        for s in strs:
            temp=[int(i) for i in s]
            numss.append(temp)
        #动态规划,01背包问题,二维的,既要满足0又要满足1
        dp=[[0] *(m+1) for t in range(n+1)] #列m 行n
        #01背包,物品在外面,里面倒叙
        for num in numss:
            one=0
            zero=0
            for i in num:
                if i==0:zero+=1
                else:one+=1
            for j in range(n,one-1,-1):
                for k in range(m,zero-1,-1):
                        dp[j][k]=max(dp[j][k],dp[j-one][k-zero]+1)
                        
        return dp[n][m]
"""
统计字符串中某个字符的 个数: ss.count("s")
"""

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值