这类题往往采用动态规划,但是注意动态规划dp的含义。与其他不同,这一类的dp[i][j]/dp[i]定义为:以索引 i 字符结尾的最长递增/重复的长度,所有这一类题往往还需要一个变量记录最大的那个结果!
最长公共前缀
# class Solution:
# def longestCommonPrefix(self, strs: List[str]) -> str:
# if not strs: return ""
# res = ""
# for s in zip(*strs):
# t = set(s)
# if len(t) == 1:
# res += s[0]
# else:
# break
# return res
# class Solution:
# def longestCommonPrefix(self, strs: List[str]) -> str:
# if not strs: return ""
# s1 = min(strs)
# s2 = max(strs)
# for i in range(len(s1)):
# if s1[i] != s2[i]:
# return s1[:i]
# return s1
# 分治
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
def fun(start, end):
if start == end:
return strs[start]
mid = (start + end) >> 1
left, right = fun(start, mid), fun(mid + 1, end)
minlength = min(len(left), len(right))
for i in range(minlength):
if left[i] != right[i]:
return left[:i]
return left[:minlength]
return "" if not strs else fun(0, len(strs) - 1)
最长递增序列
# class Solution:
# def lengthOfLIS(self, nums: List[int]) -> int:
# n = len(nums)
# if n <= 1:
# return n
# dp = [1 for _ in range(n)]
# result = 1
# for i in range(1, n):
# for j in range(i):
# if nums[i] > nums[j]:
# dp[i] = max(dp[i], dp[j] + 1)
# if dp[i] > result: result = dp[i]
# return result
# 贪心+二分查找
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
d = [] # d[i]:长度为 i + 1 的最长上升子序列的末尾元素的最小值
for num in nums:
if not d or num > d[-1]:
d.append(num)
else:
l, r = 0, len(d) - 1
loc = r
while l <= r:
mid = (l + r) >> 1
if d[mid] >= num:
loc = mid
r = mid - 1
else:
l = mid + 1
d[loc] = num
return len(d)
最长连续递增序列
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
n = len(nums)
if n <= 1:
return n
dp = [1 for _ in range(n)]
result = 0
for i in range(1, n):
if nums[i] > nums[i - 1]:
dp[i] = dp[i - 1] + 1
if dp[i] > result:
result = dp[i]
return result
最长重复子数组
# class Solution:
# def findLength(self, A: List[int], B: List[int]) -> int:
# dp = [[0 for _ in range(len(B) + 1)] for _ in range(len(A) + 1)]
# result = 0
# for i in range(1, len(A) + 1):
# for j in range(1, len(B) + 1):
# if A[i- 1] == B[j - 1]:
# dp[i][j] = dp[i - 1][j - 1] + 1
# if dp[i][j] > result: result = dp[i][j]
# return result
# class Solution:
# def findLength(self, A: List[int], B: List[int]) -> int:
# dp = [0 for _ in range(len(B) + 1)]
# result = 0
# for i in range(1, len(A) + 1):
# for j in range(len(B), 0, -1):
# if A[i - 1] == B[j - 1]:
# dp[j] = dp[j - 1] + 1
# else: dp[j] = 0
# if result < dp[j]:
# result = dp[j]
# return result
# 滑动窗口
class Solution:
def findLength(self, A: List[int], B: List[int]) -> int:
m, n = len(A), len(B)
res = 0
for i in range(m):
length = min(m - i, n)
res = max(self.fun(A, B, i, 0, length), res)
for i in range(n):
length = min(m, n - i)
res = max(res, self.fun(A, B, 0, i, length))
return res
def fun(self, A, B, ia, ib, length):
res, k = 0, 0
for i in range(length):
if A[ia + i] == B[ib + i]:
k += 1
res = max(res, k)
else:
k = 0
return res
最长公共子序列
# class Solution:
# def longestCommonSubsequence(self, text1: str, text2: str) -> int:
# m, n = len(text1), len(text2)
# dp = [[0] * (n + 1) for _ in range(m + 1)]
# for i in range(1, m + 1):
# for j in range(1, n + 1):
# if text1[i - 1] == text2[j - 1]:
# dp[i][j] = 1 + dp[i - 1][j - 1]
# else:
# dp[i][j] = max(dp[i -1][j], dp[i][j -1])
# return dp[-1][-1]
#压缩
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m, n = len(text1), len(text2)
dp = [0] * (n + 1)
for i in range(1, m + 1):
pre = 0
for j in range(1, n + 1):
temp = dp[j]
if text1[i - 1] == text2[j - 1]:
dp[j] = 1 + pre
else:
dp[j] = max(dp[j], dp[j -1])
pre = temp
return dp[-1]
与该题类似的题:不相交的线
最大子序和
# 动态规划,dp[i]:以索引i结尾的最大序列和的值
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
target = nums[0]
dp = [nums[0] for _ in range(len(nums))]
for i in range(1, len(nums)):
dp[i] = max(dp[i - 1] + nums[i], nums[i])
if dp[i] > target:
target = dp[i]
return target
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
target = float('-inf')
count = 0
for i in range(len(nums)):
count += nums[i]
if count > target:
target = count
if count <= 0: count = 0
return target