515 字
3 分钟
代码随想录算法训练营第三十七天 | 动态规划 Part10
300. 最长递增子序列
LeetCode 300. Longest Increasing Subsequence
思路:
- 定义
dp[i]
表示以下标i
结尾的最长递增子序列的长度; - 遍历
j
在i
之前的元素,如果nums[i] > nums[j]
,说明可以接在后面; - 状态转移方程:
dp[i] = max(dp[i], dp[j] + 1)
- 最终答案是
max(dp)
中的最大值。
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: dp = [1] * len(nums) # 每个元素都至少可以单独成为子序列 for i in range(len(nums)): for j in range(i): if nums[i] > nums[j]: # 如果当前元素大于前一个元素,则可以接在其后面 dp[i] = max(dp[i], dp[j] + 1) return max(dp) # 返回最长子序列长度
674. 最长连续递增序列
LeetCode 674. Longest Continuous Increasing Subsequence
思路:
- 定义
dp[i]
表示以第i
个元素结尾的最长连续递增子序列的长度; - 若
nums[i] > nums[i - 1]
,说明可以延续前面的连续递增序列; - 否则,重新开始计数;
- 最终返回
max(dp)
。
class Solution: def findLengthOfLCIS(self, nums: List[int]) -> int: n = len(nums) dp = [1] * n # 每个元素至少是长度为1的连续递增序列 for i in range(n): if i > 0 and nums[i] > nums[i - 1]: # 当前数比前一个数大,延续递增序列 dp[i] = max(dp[i - 1] + 1, dp[i]) return max(dp) # 返回最大长度
718. 最长重复子数组
LeetCode 718. Maximum Length of Repeated Subarray
思路:
- 本题类似于“最长公共子串”;
- 定义
dp[i][j]
表示以nums1[i-1]
和nums2[j-1]
结尾的最长相同子数组长度; - 若
nums1[i - 1] == nums2[j - 1]
,则dp[i][j] = dp[i-1][j-1] + 1
; - 否则
dp[i][j] = 0
; - 答案是所有
dp[i][j]
中的最大值。
class Solution: def findLength(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) # 多加一行一列,方便处理边界情况 dp = [[0] * (n + 1) for _ in range(m + 1)] res = 0 # 记录最大长度 for i in range(1, m + 1): for j in range(1, n + 1): if nums1[i - 1] == nums2[j - 1]: # 若元素相等,则在之前的基础上+1 dp[i][j] = dp[i - 1][j - 1] + 1 res = max(res, dp[i][j]) # 更新最大值 return res
代码随想录算法训练营第三十七天 | 动态规划 Part10
https://fuwari.vercel.app/posts/code_musings_day_thirty-seven/