第八篇:动态规划
动态规划就三步:
第一步:定义数组元素的含义,如dp[i]代表什么意思,dp[i][j]代表什么意思。定义出一个合适的数组,是关键点,也是最难点。
第二步:找出数组元素之间的关系,即状态转移方程
第三步:先找出初始值,然后循环遍历数组,给数组其他元素赋值
leetcode题目:
力扣70、爬楼梯。easy。
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
这道题有一个关键点就是【爬到第n阶的办法数】=【爬到第n-1阶的办法】+【爬到第n-2阶的办法】。这是总结归纳出来的,过程如下:
n=1时,只有1种方法,即【1个1】
n=2时,有2种方法,即【2个1】,或【1个2】
n=3时,有3种方法,即【3个1】,或【1个1,1个2】,或【1个2,1个1】
n=4时,有5种方法,即【4个1】,或【2个2】,或【1个1,1个2,1个1】,或【1个2,2个1】,或【2个1,1个2】
当n≥3时,需要建一个数组arr,数组长度为n+1。arr[n]表示爬到第n阶的办法数。对于任意一个索引大于等于3的元素,值都是前两个元素的和。
public int climbStairs(int n) {
if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
}
int[] arr = new int[n + 1];
arr[1] = 1;
arr[2] = 2;
for (int i = 3; i < arr.length; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}
第一步,定义数组元素的含义。arr[i]表示爬到第i阶的办法数
第二步,找出数组元素之间的关系。arr[i] = arr[i - 1] + arr[i - 2]
第三步,找出初始值,并循环遍历数组,给数组其他元素赋值。arr[1]=1,arr[2]=2,for 。。。
以上,如果不定义数组,而是采用递归方法,那么判断完n=1、n=2的情况后,就需要返回ClimbStairs(n-1) + ClimbStairs(n-2)了。这种方法实测,当n比较大时,函数耗时会非常长。而采用数组存储中间值,即使n很大,函数耗时也会很短。在算法题中,递归算法一般用于解涉及到二叉树的题。
力扣5、最长回文子串。med。
对于一个字符串而言,如果它是回文串,并且长度大于2,那么将它首尾的两个字母去除之后,它仍然是个回文串。根据这样的思路,我们就可以用动态规划的方法解决本题。
首先定义数组元素的含义,定义一个数组dp[][],dp[i][j]值为1表示s[i:j]不是回文串,值为2表示s[i:j]是回文串。s[i:j]表示索引从i到j的字符串,包括i和j。
其次定义状态转移方程,dp[i][j] = (arr[i] == arr[j] && dp[i + 1][j - 1] == 2) ? 2 : 1,arr是原始字符串转换的字符数组。dp[i][j]的值依赖dp[i+1][j-1]的值,也就是说要先计算出dp[i+1][j-1]的值,才能计算出dp[i][j]的值。从二维数组对应的表格来看,先计算左下角的值,再计算右上角的值。利用外层遍历列,内层遍历行的方式,即可从左到右一列一列给数组赋值。二维数组既可以外层遍历行,也可以外层遍历列,这是很基础的知识。
力扣409、最长回文串。med。
题目和力扣5相似,所以一起研究下。
力扣53、最大子数组和。med。
思路:定义一个一维数组dp,dp[i]表示以nums[i]结尾的连续子数组的最大和。dp[i]=max(dp[i-1]+nums[i], nums[i])。
力扣62、不同路径。med。
首先定义数组元素的含义,创建一个二维数组,定义dp[i][j]的值是机器人从左上角移动到位于索引i行、索引j列的方块的路径数(i、j都从0开始,表示第一行、第一列)。因为机器人每次只能向下或者向右移动一步,故dp[i][j] = dp[i-1][j] + dp[i][j-1]。i等于0时,dp[i][j]等于1。i≥1时,如果j等于0,dp[i][j]等于1,如果j≥1,则dp[i][j] = dp[i-1][j] + dp[i][j-1]。
力扣63、不同路径II。med。
首先定义数组元素的含义,创建一个二维数组,定义dp[i][j]的值是机器人从左上角移动到位于索引i行、索引j列的方块的路径数(i、j都从0开始,表示第一行、第一列)。如果索引i行、索引j列的方块上有障碍,则dp[i][j]值为0,否则在i>0、j>0时,dp[i][j]=dp[i-1][j] + dp[i][j-1],即dp[i][j] = obstacleGrid[i][j] == 1 ? 0 : dp[i-1][j] + dp[i][j-1]。i=0是第一行的情况,第一行不用考虑从上面下来的情况,只需考虑从左边过来的情况,j=0是第一列的情况,第一列不用考虑从左边过来的情况,只需考虑从上面下来的情况,则dp[i][j] = obstacleGrid[i][j] == 1 ? 0 : (i - 1 < 0 ? 0 : dp[i-1][j]) + (j - 1 < 0 ? 0 : dp[i][j-1]。但是这样算下来,dp所有元素值都为0。这是因为dp[0][0]等于0了,而dp[0][0]在obstacleGrid[i][j]值等于1时为0,在obstacleGrid[i][j]值等于0时为1。赋此初始值之后,就可以正确算出dp各元素值了。
力扣980、不同路径III。hard。
首先定义数组元素的含义。
力扣64、最小路径和。med。
思路:同53题
浙公网安备 33010602011771号