动态规划算法练习(5)--medium

时间:2022-07-24
本文章向大家介绍动态规划算法练习(5)--medium,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
1. 预测赢家(leetcode 486. Predict the Winner)

中文链接:https://leetcode-cn.com/problems/predict-the-winner/ 英文链接:https://leetcode.com/problems/predict-the-winner/

题目:

我们可以分成两种情况来考虑,当这个数组数目是偶数时,先手是必胜的。在选择同样数目的数字时,先手可以选择加和更大的组合; 对于总数目是奇数的情况,我们可以构建一个二维数组dp,来存放第i到j位置的这些数字先手和后手的得分差值。比如说,对于示例2,当i=0, j=0时,只有一种选择,也就是先手拿1,差值为1,dp[0][0] = 1;当i=0, j = 1时,数组为[1,5],先手拿5,后手拿1,差为4,dp[0][1] = 4;....... 那么,在dp[i][j]位置的值是什么呢? 假如先手拿nums[i],那么与后手的差就是nums[i] - dp[i+1][j];先手拿nums[j],那么与后手的差即nums[j] - dp[i][j-1]。以下是python实现:

class Solution:
    def PredictTheWinner(self, nums: List[int]) -> bool:
        n = len(nums)
        if not n % 2:
            return True
        
        dp = [[0 for x in range(n)] for y in range(n)]
        for i in range(n):
            dp[i][i] = nums[i]
            
        for i in range(n-2, -1, -1):
            for j in range(i+1, n):
                dp[i][j] = max(nums[i] - dp[i+1][j], nums[j] - dp[i][j-1])
        
        return dp[0][-1]>=0
2. 打家劫舍 II (213. House Robber II)

中文链接:https://leetcode-cn.com/problems/house-robber-ii/ 英文链接:https://leetcode.com/problems/house-robber-ii/

image.png

打家劫舍的进阶版题型。不能同时选首位和末尾数字。所以这里可以构建一个n行两列的数组,第一列表示第一个数字而不选最后一个,第二列表示选择最后一个数。其他的地方与打家劫舍I一样。python实现:

class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        
        n = len(nums)

        if n <= 3:
            return max(nums)
        else:
            dp = [[0,0] for x in range(n)]
            dp[0][0],dp[1][0] = nums[0], max(nums[0], nums[1])
            dp[1][1], dp[2][1] = nums[1], max(nums[1], nums[2])

            for i in range(2, n - 1):
                dp[i][0] = max(dp[i-2][0] + nums[i], dp[i-1][0])
                dp[i+1][1] = max(dp[i-1][1] + nums[i+1], dp[i][1])

            return max(dp[-1][1], dp[-2][0])