1. 最长公共子序列(Longest Common Subsequence, LCS)

题目描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

解题思路

使用动态规划,创建一个二维数组 dp,其中 dp[i][j] 表示 text1[0...i-1] 和 text2[0...j-1] 的最长公共子序列的长度。

代码实现

def longestCommonSubsequence(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]

2. 编辑距离(Edit Distance)

题目描述

给定两个单词 word1 和 word2,计算出将 word1 转换为 word2 所使用的最少操作次数。

解题思路

同样使用动态规划,dp[i][j] 表示 word1[0...i-1] 转换为 word2[0...j-1] 的最小编辑距离。

代码实现

def minDistance(word1, word2):

m, n = len(word1), len(word2)

dp = [[0] * (n + 1) for _ in range(m + 1)]

for i in range(m + 1):

for j in range(n + 1):

if i == 0:

dp[i][j] = j

elif j == 0:

dp[i][j] = i

elif word1[i - 1] == word2[j - 1]:

dp[i][j] = dp[i - 1][j - 1]

else:

dp[i][j] = 1 + min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1])

return dp[m][n]

3. 不同的子序列(Distinct Subsequences)

题目描述

给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

解题思路

依然使用动态规划,dp[i][j] 表示 S[0...i-1] 中包含 T[0...j-1] 的不同子序列的个数。

代码实现

def numDistinct(S, T):

m, n = len(S), len(T)

dp = [[0] * (n + 1) for _ in range(m + 1)]

for i in range(m + 1):

dp[i][0] = 1

for i in range(1, m + 1):

for j in range(1, n + 1):

if S[i - 1] == T[j - 1]:

dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]

else:

dp[i][j] = dp[i - 1][j]

return dp[m][n]

4. 最大子序和(Maximum Subarray)

题目描述

给定一个整数数组 nums,找到一个具有最大和的连续子数组(至少包含一个数字),并返回其最大和。

解题思路

使用动态规划,dp[i] 表示以 nums[i] 结尾的最大子序和。

代码实现

def maxSubArray(nums):

n = len(nums)

dp = [0] * n

dp[0] = nums[0]

max_sum = dp[0]

for i in range(1, n):

dp[i] = max(nums[i], dp[i - 1] + nums[i])

max_sum = max(max_sum, dp[i])

return max_sum

5. 最小路径和(Minimum Path Sum)

题目描述

给定一个包含非负整数的 m x n 网格 grid,找出一条从左上角到右下角的路径,使得路径上的数字总和最小。

解题思路

使用动态规划,dp[i][j] 表示从左上角到 (i, j) 的最小路径和。

代码实现

def minPathSum(grid):

m, n = len(grid), len(grid[0])

dp = [[0] * n for _ in range(m)]

dp[0][0] = grid[0][0]

# 初始化第一行和第一列

for i in range(1, m):

dp[i][0] = dp[i-1][0] + grid[i][0]

for j in range(1, n):

dp[0][j] = dp[0][j-1] + grid[0][j]

# 填充剩余的 dp 表

for i in range(1, m):

for j in range(1, n):

dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]

return dp[-1][-1]

以上五个算法问题都是经典的高难度问题,它们在面试和算法竞赛中经常出现。通过动态规划的方式,我们可以有效地解决这些问题。希望这篇博客能帮助您更好地理解这些算法问题及其解决方案。如果您有任何疑问或建议,欢迎在评论区留言。