子序列不连续,子数组连续
300. 最长递增子序列
- nlog(n)时间复杂度的动态规划
- dp[i] = max(dp[i],dp[j]+1)
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = [0]*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) + 1 ## 注意返回值
674. 最长连续递增序列
- 比上题简单,只需记住前一个数字的最长连续数量即可
- dp[i] = dp[i-1] + 1
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
dp = [1]*len(nums)
for i in range(1,len(nums)):
if nums[i]>nums[i-1]:
dp[i] = dp[i-1] + 1
return max(dp)
718. 最长重复子数组
- ** if nums1[i]==nums2[j]: dp[i][j] = dp[i-1][j-1] + 1**
- dp长度等于数组长度时,在[0,0,0,0,1]和[1,0,0,0,0]这两个用例出错了。是因为没有对i,j进行大于等于1判断,
- 另外一个解决办法是将dp长度扩展一行一列
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
res = 0
dp = [[0]*len(nums2) for _ in range(len(nums1))]
for i in range(len(nums1)):
for j in range(len(nums2)):
if nums1[i]==nums2[j]:
if i>=1 and j>=1:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = 1
if dp[i][j]>res:
res = dp[i][j]
return res
1143.最长公共子序列
- 该题目不要求连续的公共子序列
- 相等时一定等于对角线+1(肯定大于等于左侧和上侧的数)
- 不相等时等于max(左侧,上侧)
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
dp = [[0]*(len(text2)+1) for _ in range(len(text1)+1)]
res = 0
for i in range(len(text1)):
for j in range(len(text2)):
if text1[i]==text2[j]:
## 对角线加一一定是大于等于左侧和上侧的数字的
# dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j],dp[i][j] + 1)
dp[i+1][j+1] = dp[i][j] + 1
else:
dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j])
if res< dp[i+1][j+1]:
res = dp[i+1][j+1]
return res
## 这里其实可以直接返回最后一个值
# return dp[-1][-1]
1035.不相交的线
- 题目花里胡哨,其实这个题与1143.最长公共子序列是一样的
class Solution:
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
res = 0
for i in range(len(nums1)):
for j in range(len(nums2)):
if nums1[i]==nums2[j]:
dp[i+1][j+1] = dp[i][j] + 1
else:
dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j])
return dp[-1][-1]
53.最大子数组和
- 之前用过贪心算法,其实简化版动规即贪心
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = nums[0]
ans = nums[0]
for i in range(1,len(nums)):
dp = max(nums[i],dp+nums[i])
if ans<dp:
ans = dp
return ans
1749. 任意子数组和的绝对值的最大值
- 刚好今天做到的一个题与53.最大子数组和类似,求得是连续子数组的和,这里要求的是绝对值的最大值,因此用两个dp来维护最大和最小即可
class Solution:
def maxAbsoluteSum(self, nums: List[int]) -> int:
dp = [0,0]
res = 0
for i in nums:
dp[0] = max(i,dp[0]+i,0)
dp[1] = min(i,dp[1]+i,0)
## 其实改成如下也能AC
# dp[0] = max(i,dp[0]+i)
# dp[1] = min(i,dp[1]+i)
res = max(res,dp[0],abs(dp[1]))
return res