53、最大子数组问题
基本思想:
动态规划
具体实现:
1、确定状态
(1)最后一步-----以nums[i]结尾的“最大子数组和”
(2)子问题----以nums[i-1]结尾的“最大子数组和”
知道了nums列表中以每一个数字结尾的最大子数组和,找出其中最大的就可以了
2、转移方程
dp[i]=max(nums[i],nums[i]+dp[i-1])
与前面的相邻子树组连接,形成一个更大的子数组。
不予前面的子数组连接,自己作为一个子数组。
3、初始条件
dp数组初始都为0
dp[0]=nums[0]
4、计算顺序
从前往后
5、状态压缩
计算出dp数组后,还要找其中的最大值,需要两个循环
因为dp[i]只与dp[i-1]有关,所以只要设两个变量记录就可,不需要设出dp数组
代码:
class Solution: def maxSubArray(self, nums: List[int]) -> int: n = len(nums) if n == 0: return 0 dp_0 = nums[0] dp_1 = 0 res = dp_0 for i in range(1,n): dp_1 = max(nums[i], nums[i]+dp_0) dp_0 = dp_1 res = max(res,dp_1) return res
1143、最长公共子序列
基本思想:
动态规划
具体实现:
1、确定状态:
(1)最后一步---dp[i][j]是对于s1[0:i-1]和s2[0:j-1],它们的最长公共子序列长度
(2)子问题---dp[i-1][j],dp[i][j-1],dp[i-1][j-1]
2、转移方程:
(1)如果s1[i] == s2[j],说明有一个公共字符
dp[i][j] = dp[i-1][j-1] +1
(2)如果s1[i] != s2[j],说明至少有一个字符不是公共字符
dp[i][j] = max(dp[i-1][j],dp[i][j-1])
3、初始状态:
让索引为0的行和列表示空串,dp[0][...]
和 dp[...][0]
都应该初始化为0
4、计算顺序:
从上往下,从左到右
代码:
class Solution: def longestCommonSubsequence(self, text1: str, text2: str) -> int: m = len(text1) n = len(text2)
dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
# 可以不加1,但是不加1就会用其它限制条件来确保这个index是有效的,加1之后就不需要去判断 # 只是让索引为0的行和列表示空串 for i in range(1,m+1): for j in range(1,n+1): if text1[i-1] == text2[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i][j-1],dp[i-1][j]) return dp[m][n]