算法学习|线性dp
线性动态规划(Linear DP)
处理序列或线性结构上的最优化问题,状态转移沿单一方向进行
最长递增子序列(LIS)
问题:找到数组中最长的严格递增子序列长度。
状态:dp[i] 表示以 nums[i] 结尾的 LIS 长度。
转移方程:dp[i] = max(dp[j] + 1) 对所有 j < i 且 nums[j] < nums[i]
def length_of_lis(nums):
n = len(nums)
dp = [1] * n
for i in range(n):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp) if n > 0 else 0
nums = [10, 9, 2, 5, 3, 7, 101, 18]
print(length_of_lis(nums))
# 输出 4(子序列 [2,5,7,101])
最长公共子序列(LCS)
问题:给定两个字符串 text1 和 text2,返回它们的最长公共子序列长度。
状态定义:dp[i][j] 表示 text1[0:i-1] 和 text2[0:j-1] 的 LCS 长度。
转移方程:
若 text1[i-1] == text2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
否则:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
def longest_common_subsequence(text1, text2):
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] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
text1 = "abcde"
text2 = "ace"
print(longest_common_subsequence(text1, text2))
# 输出 3("ace")
最大子数组和(Kadane算法)
问题:找到数组中连续子数组的最大和。
状态定义:dp[i] 表示以 nums[i] 结尾的最大子数组和。
转移方程:
dp[i] = max(nums[i], dp[i-1] + nums[i])
def max_subarray(nums):
max_sum = current_sum = nums[0]
for num in nums[1:]:
current_sum = max(num, current_sum + num)
max_sum = max(max_sum, current_sum)
return max_sum
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
print(max_subarray(nums))
# 输出 6(子数组 [4,-1,2,1])
编辑距离
问题:将字符串 word1 转换为 word2 所需的最小操作数(插入、删除、替换)。
状态定义:dp[i][j] 表示 word1[0:i-1] 到 word2[0:j-1] 的最小操作数。
转移方程:
若 word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
否则:
dp[i][j] = 1 + min(
dp[i-1][j], # 删除 word1[i-1]
dp[i][j-1], # 插入 word2[j-1]
dp[i-1][j-1] # 替换
)
def min_edit_distance(word1, word2):
m, n = len(word1), len(word2)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1): dp[i][0] = i # 删除所有字符
for j in range(n+1): dp[0][j] = j # 插入所有字符
for i in range(1, m+1):
for j in range(1, n+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
return dp[m][n]
print(min_edit_distance("horse", "ros"))
# 3 可能?(horse→rorse→rose→ros)

浙公网安备 33010602011771号