文章目录
25.最长递增子序列
300.最长递增子序列
dp[i]表示前i个数中的最长递增子序列
dp[i]=max(0到i-1中比i小的dp[j]+1)
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = [1]*len(nums)
for i in range(1,len(nums)):
for j in range(i):
if nums[i]>nums[j]:
dp[i] = max(dp[i],dp[j]+1)
print(dp)
return max(dp)
26.最长连续递增序列
674. 最长连续递增序列
只与前一个值进行比较
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
print(dp)
return max(dp)
27.最长重复子数组
718. 最长重复子数组
返回二维dp数组的全部最大值
初始化时多添一行0和一列0
若两个当前值相等,dp[i][j] = dp[i-1][j-1]+1
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
r = 0
dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
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
if max(dp[i])>r: r = max(dp[i])
return r
28.最长公共子序列
1143.最长公共子序列
若两值相等,更新值为前面行和列中最大值+1
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
r = [0]*(len(text1)+1)
dp = [[0]*(len(text1)+1) for _ in range(len(text2)+1)]
for i in range(1,len(text2)+1):
for j in range(1,len(text1)+1):
if text2[i-1]==text1[j-1]:
dp[i][j]=max(r[:j])+1
for j in range(1,len(text1)+1):
r[j] = max(dp[i][j],r[j])
print(dp)
return max(r)
29.不相交的线
1035.不相交的线
同28,即求最长公共子序列
class Solution:
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
r = [0]*(len(nums1)+1)
dp = [[0]*(len(nums1)+1) for _ in range(len(nums2)+1)]
for i in range(1,len(nums2)+1):
for j in range(1,len(nums1)+1):
if nums2[i-1]==nums1[j-1]:
dp[i][j]=max(r[:j])+1
for j in range(1,len(nums1)+1):
r[j] = max(dp[i][j],r[j])
print(dp)
return max(r)
30.最大子序和
53. 最大子序和
dp[i] = max(dp[i-1]+nums[i],nums[i])
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = [0]*len(nums)
dp[0]=nums[0]
for i in range(1,len(nums)):
dp[i] = max(dp[i-1]+nums[i],nums[i])
return max(dp)
31.判断子序列
392.判断子序列
最长公共子序列的值是否与较短字符串长度相等
若当前比较值相等,dp值为左上+1
若不相等,dp值为左
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
for i in range(1,len(s)+1):
for j in range(1,len(t)+1):
if s[i-1]==t[j-1]:
dp[i][j] = dp[i-1][j-1]+1
else:
dp[i][j] = dp[i][j-1]
return dp[-1][-1]==len(s)
32.不同的子序列
115.不同的子序列
若相同,带t[i]的子序列数+在s[:j]中删掉s[j]
若不相同,在s[:j]中删掉s[j]
class Solution:
def numDistinct(self, s: str, t: str) -> int:
dp = [[0]*(len(s)+1) for _ in range(len(t)+1)]
dp[0][0]=1
for i in range(len(s)):
dp[0][i+1]=1
for i in range(1,len(t)+1):
for j in range(1,len(s)+1):
if t[i-1]==s[j-1]:
dp[i][j] = dp[i-1][j-1]+dp[i][j-1]
else:
dp[i][j] = dp[i][j-1]
return dp[-1][-1]
33.两个字符串的删除操作
583. 两个字符串的删除操作
构建二维dp数组时多加一行一列
初始化时,第一行及第一列为0123…
递推公式,相同时为左上,不同时为min(左上+2,左+1,上+1)
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp = [[0]*(len(word1)+1) for _ in range(len(word2)+1)]
for i in range(len(word1)):
dp[0][i+1] = i+1
for i in range(len(word2)):
dp[i+1][0] = i+1
for i in range(1,len(word2)+1):
for j in range(1,len(word1)+1):
if word2[i-1]==word1[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=min(dp[i-1][j-1]+2,dp[i-1][j]+1,dp[i][j-1]+1)
return dp[-1][-1]
34.编辑距离
72. 编辑距离
若相同,和dp[i-1][j-1]一样
若不同,min(删,增,改)
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp = [[0]*(len(word1)+1) for _ in range(len(word2)+1)]
for i in range(1,len(word1)+1):
dp[0][i]=i
for i in range(1,len(word2)+1):
dp[i][0]=i
print(dp)
for i in range(1,len(word2)+1):
for j in range(1,len(word1)+1):
if word2[i-1]==word1[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=min(dp[i-1][j-1]+1,dp[i][j-1]+1,dp[i-1][j]+1)
print(dp)
return dp[-1][-1]
35.回文子串
647. 回文子串
dp[i][j]表示s[i:j]是否回文
从后向前逐个作为分割点,i向前走,j向后走
s[i]==s[j]时,若ij相等或相邻,或s[i:j]回文,则回文串数量+1
class Solution:
def countSubstrings(self, s: str) -> int:
r = 0
dp = [[False]*len(s) for _ in range(len(s))]
for i in range(len(s)-1,-1,-1):
for j in range(i,len(s)):
if s[i]==s[j]:
if j-i<=1:
r += 1
dp[i][j] = True
elif dp[i+1][j-1]:
r += 1
dp[i][j] = True
return r
36.最长回文子序列
516.最长回文子序列
dp[i][j]表示s[i:j]回文子序列数量
从后向前逐个作为分割点,i向前走,j向后走
s[i]==s[j]时,dp[i][j] = dp[i+1][j-1]+2,长度+2
s[i]!=s[j]时,dp[i][j] = max(dp[i][j-1],dp[i+1][j])
初始化,只有一个字母dp为1
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
dp = [[0]*len(s) for _ in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for i in range(len(s)-1,-1,-1):
for j in range(i+1,len(s)):
if s[i]==s[j]:
dp[i][j] = dp[i+1][j-1]+2
else:
dp[i][j] = max(dp[i][j-1],dp[i+1][j])
return dp[0][-1]