Leetcode刷题第十三天-动态规划
198:打家劫舍
线性数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def rob(self, nums: List[int]) -> int: 3 #dp[i]偷房间i能获得的最大价值 4 #推导公式dp[i]=max(dp[i-2]+nums[i],dp[i-1]):dp[i-1]不偷房间i,dp[i-2]+nums[i]偷房间i 5 #dp数组初始化0号房间最大价值就是nums[0],1号房间最大价值是max(nums[0],num[1]) 6 #遍历顺序:正序 7 #打印dp数组 8 n=len(nums) 9 if(n<=2): return max(nums) 10 dp=[0]*n 11 dp[0],dp[1]=nums[0],max(nums[0],nums[1]) 12 for i in range(2,n): 13 dp[i]=max(dp[i-2]+nums[i],dp[i-1]) 14 return dp[n-1]
213:打家劫舍II
链接:213. 打家劫舍 II - 力扣(LeetCode)
环形数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def rob(self, nums: List[int]) -> int: 3 #选首 4 #选尾 5 #首尾都不选 6 #去掉头或者去掉尾就是198打家劫舍,去头去尾取最大值 7 n=len(nums) 8 if(n<=3): return max(nums) 9 return max(self.rob1(nums[1:]),self.rob1(nums[:n-1])) 10 11 def rob1(self, nums): 12 n=len(nums) 13 if(n<=2): return max(nums) 14 dp=[0]*n 15 dp[0],dp[1]=nums[0],max(nums[0],nums[1]) 16 for i in range(2,n): 17 dp[i]=max(dp[i-2]+nums[i],dp[i-1]) 18 return dp[n-1]
337:打家劫舍III
链接:337. 打家劫舍 III - 力扣(LeetCode)
二叉树,树形dp,递归+动态规划
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # Definition for a binary tree node. 2 # class TreeNode: 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution: 8 def rob(self, root: Optional[TreeNode]) -> int: 9 #dp[0]当前节点偷的最大值,dp[1]当前节点不偷的最大值 10 #推导公式return max(dp) 11 #后序遍历:当前节点偷还是不偷,需要看它的值和它left+right大小,孩子有一个偷,根节点就不能 12 #打印dp数组 13 return max(self.traversal(root)) 14 def traversal(self,root): 15 if(not root): return [0,0] 16 left=self.traversal(root.left) 17 right=self.traversal(root.right) 18 #不偷 19 value1=max(left)+max(right) 20 #偷 21 value2=root.val+left[0]+right[0] 22 return[value1,value2] 23 24
121:买卖股票得最佳时机
链接:121. 买卖股票的最佳时机 - 力扣(LeetCode)
只买卖一次,不重复买卖,股票买入时,手中现金为0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, prices: List[int]) -> int: 3 #dp[i][0]第i天持有股票得最大值,dp[i][1]第i天没有股票得最大值 4 #推导公式 5 #dp[i][0] = max(dp[i - 1][0], -prices[i]) 6 #dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]) 7 #dp数组初始化dp[0]=0 8 #遍历顺序:正序 9 #打印dp数组 10 n=len(prices) 11 dp=[[-prices[0],0]] 12 for i in range(1,n): 13 buy = max(dp[i - 1][0], -prices[i]) 14 mai = max(dp[i - 1][1], prices[i] + dp[i - 1][0]) 15 dp.append([buy,mai]) 16 return max(dp[n-1])
121:买卖股票得最佳时机II
链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)
买卖多次,股票买入时,手中现金不为0,手中现金数为前一天手中没有股票得现金数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, prices: List[int]) -> int: 3 #动态规划 4 #dp[i][0]第i天持有股票得最大值,dp[i][1]第i天没有股票得最大值 5 #推导公式 6 #dp[i][0] += max(dp[i - 1][0], dp[i - 1][1]-prices[i]) 7 #dp[i][1] += max(dp[i - 1][1], prices[i] + dp[i - 1][0]) 8 #dp数组初始化dp[0]=0 9 #遍历顺序:正序 10 #打印dp数组 11 n=len(prices) 12 dp=[[-prices[0],0]] 13 for i in range(1,n): dp.append([0,0]) 14 for i in range(1,n): 15 dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]-prices[i]) 16 dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]) 17 return max(dp[n-1]) 18 ''' 19 #贪心 20 if(not prices): return 0 21 money,i=0,0 22 lens=len(prices) 23 for i in range(1,lens): 24 money+=max(0,prices[i]-prices[i-1]) 25 return money 26 '''
123:买卖股票得最佳时机III
链接:123. 买卖股票的最佳时机 III - 力扣(LeetCode)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, prices: List[int]) -> int: 3 #dp[0]第一次持有股票得最大值,dp[1]第一次没有股票得最大值,dp[2]第二次持有股票得最大值,dp[3]第一次没有股票得最大值 4 #推导公式 5 #dp[0] = max(dp[0], -prices[i]) 6 #dp[1] = max(dp[1], dp[0]+prices[i]) 7 #dp[2] = max(dp[2], dp[1]-prices[i]) 8 #dp[3] = max(dp[3], dp[2]+ prices[i]) 9 #dp数组初始化 10 #遍历顺序:正序 11 #打印dp数组 12 dp=[-prices[0],0,-prices[0],0] 13 print(dp) 14 for i in range(1,len(prices)): 15 dp[0] = max(dp[0], -prices[i]) 16 dp[1] = max(dp[1], dp[0]+prices[i]) 17 dp[2] = max(dp[2], dp[1]-prices[i]) 18 dp[3] = max(dp[3], dp[2]+ prices[i]) 19 return dp[3]
188:买卖股票得最佳时机IV
链接:188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, k: int, prices: List[int]) -> int: 3 #dp[i]偶数天持有股票得最大值,奇数天没有股票得最大值 4 #推导公式 5 #买dp[j] = max(dp[j], dp[j-1]-price) 6 #卖dp[j] = max(dp[j], dp[j-1]+price) 7 #dp数组初始化 8 #遍历顺序:正序 9 #打印dp数组 10 dp=[0]*(2*k+1) 11 for i in range(1,2*k+1,2): dp[i]=-prices[0] 12 print(dp) 13 for price in prices: 14 for j in range(1,2*k+1): 15 if(j%2): dp[j] = max(dp[j], dp[j-1]-price) 16 else: dp[j] = max(dp[j], dp[j-1]+price) 17 return dp[2*k]
链接:309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode)
初始化:dp=[-prices[0],0,0],卖出和冷冻期价值都是0
买入股票得最大价值,dp[1]是前一天卖出(也可能不卖)股票获得最大值,dp[2]前一天是冷冻期时,dp[2]的值为前前一天卖出(也可能不卖)股票获得最大值,这俩取最小值,减去当天的股票数
dp[0] = max(dp[0], min(dp[1],dp[2])-prices[i])
冷冻期,需要再dp[1]之前操作,获取前一天卖出股票的最大值,今天是冷冻期,啥都不干,最大价值肯定是前一天卖出的价值
dp[2] = dp[1]
卖出股票
dp[1] = max(dp[1], dp[0]+prices[i])
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, prices: List[int]) -> int: 3 #dp[0]第i天持有股票得最大值,dp[1]第i天没有股票得最大值,dp[2]第i天冷冻期最大值 4 #推导公式 5 #dp[0] = max(dp[0], min(dp[1],dp[2])-prices[i]) 6 #dp[2] = dp[1]( 前一天得dp[1],需要先记录dp[2],然后再计算dp[1]) 7 #dp[1] = max(dp[1], dp[0]+prices[i]) 8 #dp数组初始化dp[0]=0 9 #遍历顺序:正序 10 #打印dp数组 11 dp=[-prices[0],0,0] 12 for i in range(1,len(prices)): 13 dp[0] = max(dp[0], min(dp[1],dp[2])-prices[i]) 14 dp[2] = dp[1] 15 dp[1] = max(dp[1], dp[0]+prices[i]) 16 return dp[1]
714:买卖股票得最佳时机含手续费
链接:714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def maxProfit(self, prices: List[int], fee: int) -> int: 3 #dp[i][0]第i天持有股票得最大值,dp[i][1]第i天没有股票得最大值 4 #推导公式 5 #dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]-prices[i]) 6 #dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]+prices[i]-fee) 7 #dp数组初始化 8 #遍历顺序:正序 9 #打印dp数组 10 dp=[[-prices[0],0]] 11 for i in range(1,len(prices)): 12 buy=max(dp[i - 1][0], dp[i - 1][1]-prices[i]) 13 mai=max(dp[i - 1][1], dp[i - 1][0]+prices[i]-fee) 14 dp.append([buy,mai]) 15 return dp[len(dp)-1][1]
链接:300. 最长递增子序列 - 力扣(LeetCode)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def lengthOfLIS(self, nums: List[int]) -> int: 3 #dp[i]nums中第i号元素的最长递增子序列长度 4 #推导公式dp[i]=(dp[i-1],dp[i-1]+1) 5 #dp数组初始化dp[i]=1 6 #遍历顺序 7 #打印dp数组 8 n=len(nums) 9 dp=[1]*n 10 for i in range(1,n): 11 for j in range(i): 12 if(nums[i]>nums[j]): dp[i]=max(dp[i],dp[j]+1) 13 return max(dp)