写代码的第三十七天
子序列子序列!!!
300.最长递增子序列
思路
解决问题1:dp[i]数组的含义?到第i位的最长严格递增子序列的长度。
解决问题2:递推公式?分为两种情况,当前这个第i位究竟和前i-1位相比是不是递增的,如果不是递增的,那么dp[i]=dp[i-1],如果是递增的(dp[i]>dp[i-1]),那么dp[i]=dp[i-1]+1(因为第i位是递增的,所以要在原始i-1的基础上加一)
解决问题3:dp数组的初始化为多少?dp0的时候也就是最大到第0位的时候严格递增子序列的长度是多少,是1,所以dp0初始化位1,其他的位置随意。
解决问题4:遍历顺序是什么?丛上面的递推公式可以看出所有的i都是从i-1得到的,所以从小到大开始遍历。
错误第一版:在这里不能return dp[-1]因为-1不一定代表整个数组的最长递增子序列的长度。在这个问题中,dp 数组中的每个元素 dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度,而不是整个数组的最长递增子序列的长度。
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums:
return 0
dp = [0] * len(nums)
dp[0] = 1
for i in range(1,len(nums)):
if nums[i] > nums[i-1]:
dp[i] = dp[i-1] + 1
else:
dp[i] = dp[i-1]
return dp[-1]
正确代码:
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums:
return 0
dp = [0] * len(nums)
dp[0] = 1
for i in range(1,len(nums)):
if nums[i] > nums[i-1]:
dp[i] = dp[i-1] + 1
else:
dp[i] = dp[i-1]
return max(dp)
674. 最长连续递增序列
思路
本题和上题的区别在于当nums[i] < nums[i-1]的时候要重新计数设置dp[i]=1
正确代码:
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
if not nums:
return 0
dp = [0] * len(nums)
dp[0] = 1
for i in range(1,len(nums)):
if nums[i] > nums[i-1]:
dp[i] = dp[i-1] + 1
else:
dp[i] = 1
return max(dp)
718. 最长重复子数组
思路
解决问题1:dp[i][j]数组的含义?nums1到第i-1位同时nums2到第j-1位的最长严格递增子序列的长度。我理解的是这里是为了后续的初始化方便。
解决问题2:递推公式?当nums1[i]和nums2[j]相等的时候dp数组要加一,也就是dp[i-1][j-1]+1。
解决问题3:dp数组的初始化为多少?初始化为0即可。
解决问题4:遍历顺序是什么?从左到右从上到下。
正确代码:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
dp = [[0 for _ in range(len(nums2)+1)] for _ in range(len(nums1)+1)]
max_length = 0
for i in range(1,len(nums1)+1):
for j in range(1,len(nums2)+1):
if nums1[i-1] == nums2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
max_length = max(max_length,dp[i][j])
return max_length