动态规划二

①  70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶

示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶
class Solution:
    def climbStairs(self, n: int) -> int:
        dp=[0 for _ in range(n)]
        if n==1:
            return 1
        if n==2:
            return 2
        dp[0]=1
        dp[1]=2
        for i in range(2,n):
            dp[i]=dp[i-1]+dp[i-2]
        return dp[-1]
class Solution:
    def climbStairs(self, n: int) -> int:
            if n < 2:
                return 1
            dp = [0] * (n + 1)
            dp[0], dp[1] = 0, 1
            print("dp",dp)
            for i in range(2, n + 1):
                print("i:", i)
                dp[i] = dp[i - 1] + dp[i - 2]
                print("dp", dp)
            return dp[n-1]+dp[n]

 

③ 198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。
class Solution:
    def rob(self, nums: List[int]) -> int:

        # s=0
        # b=0

        # for i in range(0,len(nums),2):
        #     s=s+nums[i]
        # for i in range(1,len(nums),2):
        #     b=b+nums[i]
        # return max(b,s)
        dp=[0 for _ in range(len(nums))]
        dp[0]=nums[0]
        if len(nums)>=2:
            dp[1]=max(dp[0],nums[1])
        for i in range(2,len(nums)):
            dp[i]=max(dp[i-2]+nums[i],dp[i-1])
        return max(dp)





      #偷第i个房屋时的最大值
        if len(nums)==0:
            return 0
        if len(nums)<=2:
            return max(nums)
        n=len(nums)
        dp=[0]*n
        dp[0],dp[1]=nums[0],nums[1]
        dp[2]=max(dp[0]+nums[2],dp[1])
    
        for i in range(3,len(nums)):
            dp[i]=max(dp[i-2]+nums[i],dp[i-3]+nums[i])
        return max(dp)       

④ 213. 打家劫舍 II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:

输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。
示例 3:

输入:nums = [0]
输出:0

class Solution:
    def rob(self, nums: List[int]) -> int:
        def robRange(start: int, end: int) -> int:
            first = nums[start]
            second = max(nums[start], nums[start + 1])
            for i in range(start + 2, end + 1):
                first, second = second, max(first + nums[i], second)
            return second
        
        length = len(nums)
        if length == 1:
            return nums[0]
        elif length == 2:
            return max(nums[0], nums[1])
        else:
            return max(robRange(0, length - 2), robRange(1, length - 1))


class Solution:
    def rob(self, nums: List[int]) -> int:
        



        # def f(start,end,nums):
        #     dp=[0 for _ in range(len(nums)-1)]
        #     dp[0]=nums[start]
        #     dp[1]=max(dp[0],nums[start+1])
        #     for i in range(2,n-1):
        #         dp[i]=max(dp[i-2]+nums[start+i],dp[i-1])
        #     return dp[-1]    
        # n=len(nums)
        # if n<4:
        #     return max(nums)
        # else:
        #     return max(f(0,n-1,nums),f(1,n,nums))   
      

        n=len(nums)
        if n<4:
            return max(nums)
        dp=[0 for _ in range(n-1)]
        dp1=[0 for _ in range(n-1)]
        dp[0],dp1[0]=nums[0],nums[1]
        if n>=2:
            dp[1]=max(dp[0],nums[1])
            dp1[1]=max(dp1[0],nums[2])
        for i in range(2,n-1):
            dp[i]=max(dp[i-2]+nums[i],dp[i-1])
        for i in range(2, n-1 ):
            dp1[i] = max(dp1[i - 2] + nums[i+1], dp1[i - 1])
            
        return max(dp[-1],dp1[-1])







输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

1137. 第 N 个泰波那契数

泰波那契序列 Tn 定义如下: 

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

示例 2:

输入:n = 25
输出:1389537
class Solution:
    def tribonacci(self, n: int) -> int:
        if n==0:
            return 0
        if n==1 or n==2:
            return 1
        t0,t1,t2=0,1,1
        for i in range(3,n+1):
            tmp=t2
            t2=t0+t1+t2
            t0=t1
            t1=tmp
        return t2

⑤ 

740. 删除并获得点数

给你一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。

示例 2:

输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。
class Solution:
    def deleteAndEarn(self, nums: List[int]) -> int:
        maxi=max(nums)
        alist=[0] * (maxi+1)
        for i in nums:
            alist[i]+=i

        def rob(alist):
            if len(alist)<3:
                return max(alist)

            dp=[0 for _ in range(len(alist))]  
            dp[0]=alist[0]
            dp[1]=max(dp[0],alist[1])  

            for i in range(2,len(alist)):
                dp[i]=max(dp[i-1],dp[i-2]+alist[i])   
            return dp[-1]     
        return rob(alist)   

55. 跳跃游戏

难度中等1258

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
class Solution:
    def canJump(self, nums: List[int]) -> bool:
       
        cur=0  
        for i in range(len(nums)):
            if i>cur:
                return False
            cur =max(cur,i+nums[i]) 
            if cur>=len(nums):
                break
        return True        



class Solution:
    def canJump(self, nums) :
        max_i = 0       #初始化当前能到达最远的位置
        for i, jump in enumerate(nums):   #i为当前位置,jump是当前位置的跳数
            if max_i>=i and i+jump>max_i:  #如果当前位置能到达,并且当前位置+跳数>最远位置  
                max_i = i+jump  #更新最远能到达位置
        return max_i>=i

45. 跳跃游戏 II

难度中等1051

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

输入: [2,3,0,1,4]
输出: 2
class Solution:
    def jump(self, nums: List[int]) -> int:
        
        new_max,maxi,step=0,0,0
        for i in range(len(nums)-1):
            new_max=max(new_max,i+nums[i])
            if i==maxi:
                step+=1
                maxi=new_max
                if maxi>=len(nums)-1:
                    break          
        return step 



当前所能达到的最远位置 end,下一步所能跳到的最远位置 max_pos,最少跳跃次数 setps。


class Solution:
    def jump(self, nums: List[int]) -> int:
        end, max_pos = 0, 0
        steps = 0
        for i in range(len(nums) - 1):
            max_pos = max(max_pos, nums[i] + i)
            if i == end:
                end = max_pos
                steps += 1
        return steps

 

918. 环形子数组的最大和

难度中等171

给定一个由整数数组 A 表示的环形数组 C,求 C 的非空子数组的最大可能和。

在此处,环形数组意味着数组的末端将会与开头相连呈环状。(形式上,当0 <= i < A.length 时 C[i] = A[i],且当 i >= 0 时 C[i+A.length] = C[i]

此外,子数组最多只能包含固定缓冲区 A 中的每个元素一次。(形式上,对于子数组 C[i], C[i+1], ..., C[j],不存在 i <= k1, k2 <= j 其中 k1 % A.length = k2 % A.length

示例 1:

输入:[1,-2,3,-2]
输出:3
解释:从子数组 [3] 得到最大和 3

示例 2:

输入:[5,-3,5]
输出:10
解释:从子数组 [5,5] 得到最大和 5 + 5 = 10

参考:. - 力扣(LeetCode)

解题思路
参数定义
pre:以当前i结尾的最大子数组的和
max_/min_:数组中子数组和的最大最小值
思路
根据上图,本题可以分为两种情况讨论
无环:最大和子数组不包含首尾元素
有环:最大和子数组包含首尾元素
无环状态下,即为53. 最大子序和
有环状态下,要使得两端之和最大,必须让中间的子数组最小,即最后有环情况下的最大子数组和为:sum(nums)-min_
复杂度分析
时间复杂度:O(nn)
空间复杂度:O(11)


class Solution:
    def maxSubarraySumCircular(self, nums: List[int]) -> int:
        n=len(nums)   
        max_=float('-inf')
        #无环 
        pre=0
        for i in range(n):
            pre=max(0,pre)+nums[i]
            max_=max(max_,pre)
        # 如果最子数组和小于0,说明数组中全为负数,返回最大负数即可
        if max_<0:return max_
        #有环
        pre=0
        min_=float('inf')
        for i in range(n):
            pre=min(0,pre)+nums[i]
            min_=min(min_,pre)
        
        return max(max_,sum(nums)-min_)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值