爬楼梯与路径类题目记忆化递归与动态规划双解法(Leetcode题解-Python语言)

70. 爬楼梯(剑指 Offer 10- II. 青蛙跳台阶问题)

递归(英语:Recursion),是指在函数的定义中使用函数自身的方法。有意义的递归通常会把问题分解成规模缩小的同类子问题,当子问题缩写到寻常的时候,我们可以直接知道它的解。然后通过建立递归函数之间的联系(转移)即可解决原问题。

记忆化递归,就是用数组或者哈希表记录下递归过程中的计算结果,避免重复计算。

以爬楼梯为例,我们想知道爬 n 阶楼梯的方案数 f(n),由于每次只能爬 1 阶或 2 阶楼梯,所以其实如果知道爬 n - 1 阶和 n - 2 阶楼梯的方案数 f(n-1) 和 f(n-2),就能知道爬 n 阶楼梯的方案数 f(n) = f(n-1) + f(n-2)。 式子中最小为 n-2 ,根据题意 n-2 >= 0(也可以严格大于0,区别不大,后面相应修改) ,那么 n >= 2。意味着最后一次递归调用为 f(2) = f(1) + f(0),边界就是 f(1) = 1f(0) = 1

直接递归的代码如下:

class Solution:def climbStairs(self, n: int) -> int:if n <= 1:return 1return self.climbStairs(n - 1) + self.climbStairs(n - 2)

是会超时的,利用记忆化递归可以减少许多重复运算,顺利通过:

class Solution:memo = dict()def climbStairs(self, n: int) -> int:if n <= 1:return 1if n in self.memo:return self.memo[n]self.memo[n] = self.climbStairs(n-1) + self.climbStairs(n-2)return self.memo[n]

思路不难,只是用一个字典 memo 记录出现过的台阶与对应的方案数,如果有记录的话就不用往下递归了,直接返回结果即可。剑指 Offer 的题目区别只在于结果要对 1000000007 取余数。

509. 斐波那契数(剑指 Offer 10- I. 斐波那契数列)

class Solution:memo = dict()def fib(self, n: int) -> int:if n <= 1:return nif n in self.memo:return self.memo[n]self.memo[n] = self.fib(n-1) + self.fib(n-2)return self.memo[n]

求斐波那契数,除了边界,其余代码都是一样的。

1137. 第 N 个泰波那契数

class Solution:memo = dict()def tribonacci(self, n: int) -> int:if n == 0:return 0if n == 1 or n == 2:return 1if n in self.memo:return self.memo[n]self.memo[n] = self.tribonacci(n-1) + self.tribonacci(n-2) + self.tribonacci(n-3)return self.memo[n]

这题求的是泰波那契数,思路基本一样,只是递归公式中最小的是 n-3,所以 n >= 3,最后一次递归是 n =3,若知道 n = 0, 1, 2 的值即可得到 n = 3 的结果,所以递归边界可知。(题目其实给了)

746. 使用最小花费爬楼梯

class Solution:memo = dict()def minCostClimbingStairs(self, cost: List[int]) -> int:if len(cost) == 1:return 0if len(cost) == 2:return min(cost)if tuple(cost) in self.memo:return self.memo[tuple(cost)]self.memo[tuple(cost)] = min(cost[0] + self.minCostClimbingStairs(cost[1:]), cost[1] + self.minCostClimbingStairs(cost[2:]))return self.memo[tuple(cost)]

这题注意开始爬楼梯时,爬一个台阶是到 cost[0],两个台阶是到 cost[1],而不是 cost[0] 为起点。想要继续使用字典只能用可哈希对象元组,不能用数组。

说完记忆化递归,我们说说动态规划。动态规划(英语:Dynamic programming,简称DP)是通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。

我们应该留意到,动态规划的核心思路也是通过记忆化避免重复运算,实际上,动态规划中的 dp 数组(状态数组)对应的就是记忆化递归中的 memo 字典。关于动态规划的简单入门,我推荐这篇知乎文章。

总结来说就是三点:定义 dp 数组元素的含义(状态是什么)、找出 dp 数组元素间的关系式(递推公式或状态转移方程)、找出初始条件。用上面的例题进行说明:

70. 爬楼梯(剑指 Offer 10- II. 青蛙跳台阶问题)

dp 数组元素 dp[i] 的含义为:爬 i 阶楼梯的方案数。
数组元素间的关系,由最开始的分析可知,dp[i] = dp[i-1] + dp[i-2]。
初始条件为 dp[1] = 1, dp[2] = 2,注意我这里不讨论 dp[0] 的初始化,是因为题目说了 n 不可能为 0!所以我的遍历也是从 3 开始的,代码如下:

class Solution:def climbStairs(self, n: int) -> int:if n == 1 or n == 2:return ndp = [0] * (n+1)dp[1] = 1dp[2] = 2for i in range(3, n+1):dp[i] = dp[i-1] + dp[i-2]return dp[-1]

509. 斐波那契数(剑指 Offer 10- I. 斐波那契数列)

class Solution:def fib(self, n: int) -> int:if n == 0 or n == 1:return ndp = [0] * (n + 1)dp[0] = 0dp[1] = 1for i in range(2, n + 1):dp[i] = dp[i - 1] + dp[i - 2]return dp[-1]

dp[i] 的含义:i 对应的斐波那契数

递推公式:dp[i] = dp[i-1] + dp[i-2]

初始条件: dp[0] = 0, dp[1] = 1

观察到实际上每次都只改变了三个位置,所以优化写法如下:

class Solution:def fib(self, n: int) -> int:if n == 0 or n == 1:return nf1 = 0f2 = 1f3 = 0for i in range(1, n):f3 = f1 + f2f1, f2 = f2, f3return f3

1137. 第 N 个泰波那契数

class Solution:def tribonacci(self, n: int) -> int:if n == 0:return 0if n <= 2:return 1dp = [0] * (n + 1)dp[0] = 0 dp[1] = dp[2] = 1for i in range(3, n + 1):dp[i] = dp[i-3] + dp[i-2] + dp[i-1]return dp[-1]

dp[i] 的含义:i 对应的泰波那契数

递推公式:dp[i] = dp[i-3] + dp[i-2] + dp[i-1]

初始条件: dp[0] = 0, dp[1] = 1, dp[2] = 1

优化写法:

class Solution:def tribonacci(self, n: int) -> int:if n <= 1:return nif n == 2:return 1f1 = 0f2 = 1f3 = 1f4 = 2for i in range(3, n+1):f4 = f1 + f2 + f3f1, f2, f3 = f2, f3, f4return f4

746. 使用最小花费爬楼梯

class Solution:def minCostClimbingStairs(self, cost: List[int]) -> int:n = len(cost)dp = [0] * (n + 1)dp[0] = cost[0]dp[1] = cost[1]for i in range(2, n):dp[i] = cost[i] + min(dp[i-1], dp[i-2])dp[n] = min(dp[n-1], dp[n-2])return dp[n]

dp[i] 的含义:到达第 i 级台阶时最小的总花费(第一步有花费,最后一步没花费)

递推公式:dp[i] = cost[i] + min(dp[i-1], dp[i-2])

初始条件: dp[0] = cost[0], dp[1] = cost[1]

由于最后一步没花费,所以最后一个元素需要单独求。优化写法:

class Solution:def minCostClimbingStairs(self, cost: List[int]) -> int:n = len(cost)f1 = cost[0]f2 = cost[1]f3 = 0for i in range(2, n):f3 = cost[i] + min(f1, f2)f1, f2 = f2, f3f3 = min(f1, f2)return f3

62. 不同路径(剑指 Offer II 098. 路径的数目)

class Solution:def uniquePaths(self, m: int, n: int) -> int:dp = [[1 for _ in range(n)] for _ in range(m)]for i in range(1, m):for j in range(1, n):dp[i][j] = dp[i-1][j] + dp[i][j-1]return dp[m-1][n-1]

dp[i][j] 的含义:表示从 (0, 0) 出发,到 (i, j) 有 dp[i][j] 条不同的路径

递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1] (只能从上或左到达当前位置)

初始条件: dp[i][0]一定都是1,因为从 (0, 0) 的位置到 (i, 0) 的路径只有一条,dp[0][j]也同理,方便起见,就将整个 dp 二维数组都初始化为 1

for 循环是 m 和 n,因为要返回的就是 dp[m-1][n-1],符合定义。

63. 不同路径 II

class Solution:def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:m = len(obstacleGrid)n = len(obstacleGrid[0])dp = [[0 for _ in range(n)] for _ in range(m)]for i in range(m):if obstacleGrid[i][0] == 1:breakelse:dp[i][0] = 1for j in range(n):if obstacleGrid[0][j] == 1:breakelse:dp[0][j] = 1#print(dp)for i in range(1, m):for j in range(1, n):if obstacleGrid[i][j] != 1:dp[i][j] = dp[i-1][j] + dp[i][j-1]return dp[m-1][n-1]

dp[i][j] 的含义:表示从 (0, 0) 出发,到 (i, j) 有 dp[i][j] 条不同的路径

递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1] (前提是当前位置不是障碍)

初始条件: 先将整个 dp 二维数组都初始化为 0,然后 dp[i][0] (第一列)在遇到障碍之前都为 1,因为从 (0, 0) 的位置到 (i, 0) 的路径只有一条,dp[0][j](第一行)同理。

64. 最小路径和(剑指 Offer II 099. 最小路径之和)

class Solution:def minPathSum(self, grid: List[List[int]]) -> int:m = len(grid)n = len(grid[0])dp = [[0 for _ in range(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]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[m-1][n-1]

dp[i][j] 的含义:表示从 (0, 0) 出发,到 (i, j) 的最小路径之和

递推公式:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]

初始条件:dp[0][0] 就是 grid[0][0],然后第一列与第一行的最小路径之和都是唯一的,就是单纯地累加

931. 下降路径最小和

class Solution:def minFallingPathSum(self, matrix: List[List[int]]) -> int:n = len(matrix)dp = [[0 for _ in range(n)] for _ in range(n)]for j in range(n):dp[0][j] = matrix[0][j]for i in range(1, n):for j in range(n):if j == 0:dp[i][j] = min(dp[i-1][j], dp[i-1][j+1]) + matrix[i][j]elif j == n-1:dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + matrix[i][j]else:dp[i][j] = min(dp[i-1][j], dp[i-1][j+1], dp[i-1][j-1]) + matrix[i][j]return min(dp[-1])

dp[i][j] 的含义:表示从 (0, 0) 出发,到达 (i, j) 的最小路径之和

递推公式
如果在最左边的话,路径和就等于正上方和右上方两者中小的路径和加上当前的路径花费,
dp[i][j] = min(dp[i-1][j], dp[i-1][j+1]) + matrix[i][j]
如果在最右边的话,路径和就等于左上方和正上方两者中小的路径和加上当前的路径花费,
dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + matrix[i][j]
如果在中间,则路径和就等于左上方、正上方和右上方三者中小的路径和加上当前的路径花费,dp[i][j] = min(dp[i-1][j], dp[i-1][j+1], dp[i-1][j-1]) + matrix[i][j]

初始条件:dp 数组的第一层等于 matrix 第一层,实际上最左边和最右边也可以作为初始化

120. 三角形最小路径和(剑指 Offer II 100. 三角形中最小路径之和)

class Solution:def minimumTotal(self, triangle: List[List[int]]) -> int:n = len(triangle)dp = []for i in range(1, n+1):dp.append([0 for _ in range(i)])dp[0][0] = triangle[0][0]for i in range(1, n):for j in range(i+1):if j == 0:dp[i][j] = dp[i-1][j] + triangle[i][j]elif j == i:dp[i][j] = dp[i-1][j-1] + triangle[i][j]                    else:dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + triangle[i][j]return min(dp[-1])

dp[i][j] 的含义:表示从 (0, 0) 出发,到达 (i, j) 的最小路径之和

递推公式
如果在最左边的话,路径和就等于正上方的路径和加上当前的路径花费,
dp[i][j] = dp[i-1][j] + triangle[i][j]
如果在最右边的话,路径和就等于左上方的路径和加上当前的路径花费,
dp[i][j] = dp[i-1][j-1] + triangle[i][j]
如果在中间,则路径和就等于正上方和左上方两者中小的路径和加上当前的路径花费,
dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + triangle[i][j]

初始条件:dp 数组的第一层等于 triangle 第一层,实际上最左边和最右边也可以作为初始化

这题注意 j 的循环次数,在第 i 层就循环 i 次

1289. 下降路径最小和 II

困难题,我最开始的想法是,在上上题的基础上,让当前位置最小路径和等于不是当前列的路径和中最小的值再加上当前位置的路径花费:

class Solution:def minFallingPathSum(self, grid: List[List[int]]) -> int:m, n = len(grid), len(grid[0])dp = [[0] * n for _ in range(m)]dp[0][:] = grid[0][:]for i in range(1, m):for j in range(n):temp = float('inf')for k in range(n):if k != j and dp[i-1][k] < temp:temp = dp[i-1][k]dp[i][j] = temp + grid[i][j]return min(dp[-1])

但是显然,这个方法的时间复杂度是 O(m * n * n),容易超时。换一个思路,如果知道了第一层的最小路径,那么在第二层除了跟它同一列的位置,都是加上这个最小路径为最优;那同一列的位置加谁呢?第一层中第二小的路径呗。这样实际上就完成了从第一层到第二层的递推,dp 数组自然可以构建出来了。

class Solution:def minFallingPathSum(self, grid: List[List[int]]) -> int:m, n = len(grid), len(grid[0])dp = [[0] * n for _ in range(m)]dp[0][:] = grid[0][:]for i in range(1, m):# 找到最小的值minflag = dp[i-1].index(min(dp[i-1]))# 除了同一列的位置,都加上这个最小值for j in range(0, n):if j != minflag:dp[i][j] = grid[i][j] + dp[i-1][minflag]# 找到第二小的值if minflag == 0:minflag2 = min(dp[i-1][1:])elif minflag == n - 1:minflag2 = min(dp[i-1][:-1])else:minflag2 = min(min(dp[i-1][:minflag]), min(dp[i-1][minflag+1:]))# 给同一列的位置加上这个第二小的值dp[i][minflag] = grid[i][minflag] + minflag2return min(dp[-1])

343. 整数拆分

class Solution:def integerBreak(self, n: int) -> int:dp = [0 for _ in range(n+1)]dp[2] = 1for i in range(3, n+1):for j in range(1, i):# 假设对正整数 i 拆分出的第一个正整数是 j(1 <= j < i),则有以下两种方案:# 1) 将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j * (i-j)# 2) 将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j * dp[i-j]dp[i] = max(dp[i], j * (i - j), j * dp[i - j])return dp[n]

dp[i] 的含义:表示分拆数字 i,可以得到的最大乘积为 dp[i]

递推公式:dp[i] = max(dp[i], j * (i - j), j * dp[i - j])

初始条件:dp[2] = 1(dp[0] dp[1] 不应该初始化,因为没有意义)

96. 不同的二叉搜索树

class Solution:def numTrees(self, n: int) -> int:dp = [0 for _ in range(n+1)]dp[0] = 1for i in range(1, n+1):for j in range(1, i+1):dp[i] += dp[j-1] * dp[i-j]return dp[n]

dp[i] 的含义:1到 i 为节点组成的二叉搜索树的个数为 dp[i]

递推公式:dp[i] += dp[j-1] * dp[i-j]

初始条件:dp[0] = 1

当 n = 1 时,dp[1] = 1;当 n = 2 时,dp[2] = 2;当 n = 3 时,左右子树可能的数量分别为(2,0)、(1,1)、(0,2),这对应了 dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2];后面的以此类推。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 15发布,越来越像C# ?9月排名,C#增幅狠甩JAVA

2016年.NET Core首个正式版本问世&#xff0c;如今已发布到了.NET Core3.1&#xff0c;再有2个月.NET5也将如约而至&#xff0c;跨平台开发已经快5年。微软 .NET 程序管理总监 Scott 表示&#xff0c;.NET 5 是 .NET Framework 和 .NET Core 的未来&#xff0c;最终将成为一个统…

买卖股票类问题动态规划解法(Leetcode题解-Python语言)

在 Leetcode 中&#xff0c;关于买卖股票的问题共有6道&#xff0c;而这些题目是可以用相同的思维进行求解的&#xff0c;强烈推荐这篇总结&#xff0c;写得非常到位。 股票类问题的动态规划分三步走&#xff0c;1、首先明确方程的含义&#xff0c; T[i][k][0]&#xff1a;表…

leetcode1035. 不相交的线

一:题目 二:上码 class Solution { public:/**思路:1.分析题意:这里的我们要求解的是最大值,那么我们的求解过程肯定是动态变化的,举个例子2 5 1 2 510 5 2 1 5 2 如果我们一开始就让nums1[1] 5何 nums2[4] 5 相连的话 那么我们肯定不会求解出最大值那么题目中的说的直线不…

几个超级实用但很少人知道的 VS 技巧[更新]

大家好&#xff0c;今天分享几个我知道的实用 VS 技巧&#xff0c;而这些技巧我发现很多人都不知道。因为我经常在工作中遇到&#xff1a;我在同事电脑上解决问题&#xff0c;或在会议上演示代码示例时&#xff0c;使用了一些 VS “骚”操作&#xff0c;他们会好奇地问&#xf…

一般动态规划问题合集(Leetcode题解-Python语言)

118. 杨辉三角 class Solution:def generate(self, numRows: int) -> List[List[int]]:dp [[0] * i for i in range(1, numRows1)]for i in range(numRows):for j in range(len(dp[i])):# 左右两边是1&#xff0c;中间部分就是其上方两个数之和if j 0 or j i:dp[i][j] …

leetcode53. 最大子数组和(动态规划)

一:题目 二:上码 class Solution { public:int maxSubArray(vector<int>& nums) {/**动态规划:1>:确定dp数组的含义以及下标的含义dp[j]表示的是下标j之前的最大子数组和 这个就是还没有包括nums[j] 2>:确定dp数组的状态转移公式dp[j] max (dp[j-1]nums[j],n…

矩阵模拟问题合集(Leetcode题解-Python语言)

54. 螺旋矩阵&#xff08;剑指 Offer 29. 顺时针打印矩阵&#xff09; class Solution:def spiralOrder(self, matrix: List[List[int]]) -> List[int]:ans []count 0m, n len(matrix), len(matrix[0])length m * ndirections [(0, 1), (1, 0), (0, -1), (-1, 0)]x y…

基于REACT和.NET CORE集成WINDOWS身份验证

有很多方法可以向您的应用程序添加身份验证。虽然OAuth是最常见的一种&#xff0c;但这并不是您唯一的选择。今天&#xff0c;我将向您展示如何通过React和.NET Core简单地完成Windows身份验证。探索我们的选择在深入探讨之前&#xff0c;让我们简要讨论一些可用的其他选项。了…

.NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书

简介加解密现状&#xff0c;编写此系列文章的背景&#xff1a;需要考虑系统环境兼容性问题&#xff08;Linux、Windows&#xff09;语言互通问题&#xff08;如C#、Java等&#xff09;&#xff08;加解密本质上没有语言之分&#xff0c;所以原则上不存在互通性问题&#xff09;…

快速幂算法相关题目(Leetcode题解-Python语言)

50. Pow(x, n) 快速幂算法的目的&#xff0c;就是快速计算 x 的 n 次方。基本思路是把 n 视作二进制数&#xff0c;则 n 可以被分解为多个 2 的幂次方之和&#xff0c;如 12 对应 1100 等于 0∗200∗211∗221∗230*{2^0} 0*{2^1} 1*{2^2} 1*{2^3}0∗200∗211∗221∗23&…

leetcode115. 不同的子序列

一&#xff1a;题目 二:代码 class Solution { public:/**思路:动规分析走一波1>:确定dp数组以及下标的含义dp[i][j] 表示的是 以下标i-1结尾的子序列s中出现以j-1结尾的子序列t的 个数2>:确定dp数组的状态递推公式这里考虑两种状况 一种就是 s[i-1] s[j-1] 一种就是字…

栈的基础概念与经典题目(Leetcode题解-Python语言)

栈是先入后出&#xff08;后入先出&#xff09;的数据结构&#xff0c;常用操作就 push 和 pop&#xff0c;Python中用列表实现即可&#xff0c;基本概念可以看Leetbook相关章节。 普通栈 232. 用栈实现队列 class MyQueue:def __init__(self):self.stack1 []self.stack2 …

ASP.NET Core 3.x启动时运行异步任务(二)

这一篇是接着前一篇在写的。如果没有看过前一篇文章&#xff0c;建议先去看一下前一篇&#xff0c;这儿是传送门一、前言前一篇文章&#xff0c;我们从应用启动时异步运行任务开始&#xff0c;说到了必要性&#xff0c;也说到了几种解决方法&#xff0c;及各自的优缺点。最后&a…

leetcode583. 两个字符串的删除操作

一:题目 二:上码 class Solution { public:/**思路:题目给的是让求最值,那么首先就会想到的是动态规划,我们想得到答案的结果其实有多个的&#xff0c;但是我们是取最小的步数动态规划 五步走:1>:确定dp数组以及下标的含义dp[i][j]表示的是 以下标i-1结尾的字符串word1,和…

C# 中居然也有切片语法糖,太厉害了

一&#xff1a;背景 1. 讲故事昨天在 github 上准备找找 C# 9 又有哪些新语法糖可以试用&#xff0c;不觉在一个文档上看到一个很奇怪的写法: foreach (var item in myArray[0..5]) 哈哈&#xff0c;熟悉又陌生&#xff0c;玩过python的朋友对这个 [0..5] 太熟悉不过了&#x…

子串、子数组与子序列类型问题的动态规划求解(Leetcode题解-Python语言)

一般来说&#xff0c;子串和子数组都是连续的&#xff0c;而子序列是可以不连续的&#xff0c;遇到子序列问题基本上都是用动态规划求解。 53. 最大子数组和&#xff08;剑指 Offer 42. 连续子数组的最大和&#xff09; class Solution:def maxSubArray(self, nums: List[int…

跟我一起学.NetCore之中间件(Middleware)简介和解析请求管道构建

前言中间件(Middleware)对于Asp.NetCore项目来说&#xff0c;不能说重要&#xff0c;而是不能缺少&#xff0c;因为Asp.NetCore的请求管道就是通过一系列的中间件组成的&#xff1b;在服务器接收到请求之后&#xff0c;请求会经过请求管道进行相关的过滤或处理&#xff1b;正文…

leetcode647. 回文子串

一&#xff1a;题目 二&#xff1a;上码 class Solution { public:/**思路:动态规划五步走1>:确定dp数组以及下标的含义dp[i][j] 表示的是在[i,j]范围内的字串 是否是 回文子串&#xff0c;如果是的话那么dp[i][j] true2>确定dp数组的状态转移方程那么就有两种情况 s[i…

Leetcode周赛复盘——第 276 场力扣周赛

第一次参加周赛&#xff0c;AC了三道题&#xff0c;也算不错的成绩了&#xff0c;从现在开始每周的周赛我都会参加并且复盘&#xff0c;有兴趣的小伙伴可以一起讨论。 5980. 将字符串拆分为若干长度为 k 的组 class Solution:def divideString(self, s: str, k: int, fill: s…

leetcode516. 最长回文子序列

一:题目 二:上码 class Solution { public:/**思路:1.分析题意 这个是让我们求最值,那么首先想到动态规划2.动态规划1>:确定dp数组以及下标的含义dp[i][j] 表示字符串在[i,j]范围内的最长回文子序列2>:确定dp数组的状态递推公式那么就是s[i] 与 s[j] 相等 不相等两种情况…