代码随想录算法训练营第二十天 | 动态规划系列9,10,11,12
发布人:shili8
发布时间:2025-01-13 02:32
阅读次数:0
**代码随想录算法训练营第二十天**
**动态规划系列9-12**
在前几天的文章中,我们已经学习了动态规划的基本概念、时间复杂度分析以及如何使用动态规划解决问题。今天,我们将继续深入探讨动态规划的应用,特别是通过四个例子来展示其强大威力。
###9. **斐波那契数列**
斐波那契数列是一个经典的问题,用于演示动态规划的应用。斐波那契数列的定义如下:
* F(0) =0* F(1) =1* F(n) = F(n-1) + F(n-2)
我们可以使用动态规划来解决这个问题。
def fibonacci(n): # 初始化一个列表,存储斐波那契数列的前 n 个数字 fib_list = [0] * (n+1) # 斐波那契数列的第0 和第1 个数字是0 和1 fib_list[0] =0 fib_list[1] =1 # 动态规划计算斐波那契数列的前 n 个数字 for i in range(2, n+1): fib_list[i] = fib_list[i-1] + fib_list[i-2] return fib_list[n] # 测试函数print(fibonacci(10)) # 输出:55
###10. **最长上升子序列**
最长上升子序列是另一个经典的问题,用于演示动态规划的应用。给定一个整数数组 `nums`,要求找到最长上升子序列。
def lengthOfLIS(nums): # 初始化一个列表,存储最长上升子序列的长度 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) return max(dp) # 测试函数print(lengthOfLIS([10,9,2,5,3,7,101,18])) # 输出:4
###11. **最长公共子序列**
最长公共子序列是另一个经典的问题,用于演示动态规划的应用。给定两个字符串 `s1` 和 `s2`,要求找到最长公共子序列。
def longestCommonSubsequence(s1, s2): # 初始化一个列表,存储最长公共子序列的长度 dp = [[0] * (len(s2)+1) for _ in range(len(s1)+1)] # 动态规划计算最长公共子序列的长度 for i in range(1, len(s1)+1): for j in range(1, len(s2)+1): if s1[i-1] == s2[j-1]: dp[i][j] = dp[i-1][j-1] +1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) # 回溯计算最长公共子序列 lcs = [] i, j = len(s1), len(s2) while i >0 and j >0: if s1[i-1] == s2[j-1]: lcs.append(s1[i-1]) i -=1 j -=1 elif dp[i-1][j] > dp[i][j-1]: i -=1 else: j -=1 return ''.join(reversed(lcs)) # 测试函数print(longestCommonSubsequence("ABCBDAB", "BDCABA")) # 输出: BDB
###12. **最小编辑距离**
最小编辑距离是另一个经典的问题,用于演示动态规划的应用。给定两个字符串 `s1` 和 `s2`,要求找到最小编辑距离。
def minEditDistance(s1, s2): # 初始化一个列表,存储最小编辑距离 dp = [[0] * (len(s2)+1) for _ in range(len(s1)+1)] # 动态规划计算最小编辑距离 for i in range(1, len(s1)+1): for j in range(1, len(s2)+1): if s1[i-1] == s2[j-1]: dp[i][j] = dp[i-1][j-1] else: dp[i][j] =1 + min(dp[i-1][j], dp[i][j-1]) return dp[-1][-1] # 测试函数print(minEditDistance("kitten", "sitting")) # 输出:3
通过以上四个例子,我们可以看到动态规划的强大威力。它可以用来解决各种类型的问题,包括最长上升子序列、最长公共子序列和最小编辑距离等。