LeetCode - 动态规划专题

剑指 Offer 14- I. 剪绳子

思路

考虑多种解法

  1. Memoization. 记忆化。也叫从顶到底的算法。将一个列表初始化成0(或者-1在某些题中),如果不是初始化的值就直接读取,如果是的话就迭代的找符合要求的值存入。很好理解。时间复杂度 O ( 2 N ) O(2^N) O(2N),空间复杂度 O ( N ) O(N) O(N)
  2. DP,从底向顶。根据初始值,和剪下来j后不剪,和剪下来j后继续剪三种情况取最大来从底到顶地写入。时间复杂度 O ( N 2 ) O(N^2) O(N2), 空间复杂度 O ( N ) O(N) O(N)
  3. DP优化解法。用%3的余数作为保存的空间,这样只需要一次遍历就可得到最大值。时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( 1 ) O(1) O(1)
  4. 根据一点先验知识,为尽量多切,且切3的段数越多,最后结果越大。直接数学公式解决。
  5. 需要mol 1 e 9 + 7 1e^9+7 1e9+7(1000000007) 8个0

代码

class Solution:
    def cuttingRope(self, n: int) -> int:
        # 使用辅助函数
        def memoize(n):
            if n == 2: return 1
            if f[n] != 0: # 如果f[n]已经计算过,直接返回避免重复计算
                return f[n]
            res = -1
            for i in range(1, n):
                res = max(res, max(i * (n - i),i * memoize(n - i)))
            f[n] = res
            return res

        f = [0 for _ in range(n + 1)]
        return memoize(n)

DP:

class Solution:
    def cuttingRope(self, n: int) -> int:
        dp = [0 for _ in range(n+1)]
        dp[2] = 1
        for i in range(3, n+1):
            for j in range(i):
                # 分别意味着,初始,剪下来j后不剪,剪下来j后继续剪
                dp[i] = max(dp[i], max((i-j)*j, dp[i-j]*j))
        # print (dp)
        return dp[n]

DP优化:

class Solution:
    def cuttingRope(self, n: int) -> int:
        dp = [0, 1, 1]
        for i in range(3, n+1):
            dp[i%3] = max(
                        1* max(dp[(i-1)%3], i-1), 
                        2* max(dp[(i-2)%3], i-2), 
                        3* max(dp[(i-3)%3], i-3))
        return dp[n%3]

数学公式

class Solution:
    def cuttingRope(self, n: int) -> int:
        if n<= 3: return n-1
        a, b = n%3, n//3
        if a==0: return int(math.pow(3, b))
        if a==1: return int(math.pow(3, b-1)*4)
        else: return int(math.pow(3, b)*2)

收获

这道题需要学到的除了动态规划的思想,还有多种解题方式,以及根据提示一点点探索时间空间最优解法的。

剑指 Offer 42. 连续子数组的最大和

思路

  • 用dp来做,dp用来存储以当前位置为尾的子数组的最大值。
  • 改进:因为dp[i]只与dp[i-1]和num[i]有关,可以原地替换来节约空间。

代码

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = ['/' for _ in range(len(nums))]
        for i in range(len(nums)):
            if dp[i-1] == '/' or dp[i-1] <0 : dp[i] = nums[i]
            else: 
                dp[i] = dp[i-1]+nums[i]
        return max(dp)

改进:

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

分析

空间复杂度 O ( 1 ) O(1) O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值