题目:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
分析:这个题目可以使用递归或者其他的非递归方式解决,但是我这里想作为学习动态规划算法思想的最简单的一个题目来记录自己的学习历程。具体解决思路如下:
1.定义一个数组dp,数组中的元素dp[i]代表的含义是跳到第i阶台阶一共有多少种方法;
2.找出这个数组元素之间的关系式,那我们可以分析,跳到第n阶台阶的前一步,人可能处于第几阶台阶,从题目中知道每次可以爬1个或者2个台阶,也就是说,到达第n阶的前一步既可以是从第n-1阶爬一个台阶上去的,
也可是从第n-2阶爬两个台阶上去的,所以就有以下的关系式:
dp[i] = dp[i-1] + dp[i-2]
3.找初始值,也就是首先数组索引必须在合法的范围内,然后又能够使数组的索引值分解的足够小,所以我们根据题目可以直接找到,当n=0时,dp[n] = 0;n=1时,dp[n] = 1;n=2时,d[n] = 2;但是dp[2]是不能被dp[1]+dp[0]直接推出的,所以把dp[0]作为一个特殊值处理,不让他参与关系式运算,然后把dp[1]和dp[2]作为初始值。
代码如下:
public int climbStairs(int n) { if (n <= 2) return n;
int pre1 = 1; int pre2 = 2; for (int i = 2; i < n; i++) { int cur = pre1 + pre2; pre1 = pre2; pre2 = cur; } return pre2; }
题目来源:力扣第70题:https://leetcode-cn.com/problems/climbing-stairs/
题目:给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
分析:使用动态规划来分析解决,
1.首先定义一个二维数组dp,这个二维数组中的元素对应网格中的某个位置,则dp[i][j]就表示从左上角到(i,j)位置处所经历的路径上的最小和;
2.寻找数组中的元素之间的关系式,从题目说明可以看出,每次只能向下或者向右移动一步,所以dp[i][j] = min(dp[i-1][j],dp[i][j-1])这个等式可以代表数组的元素之间的关系;
3.确定初始值和边界值,这两个都是至关重要的,首先确定边界值,首先我们根据第二步的关系式可以知道,i和j是不能等于0,否则会发生数组越界异常,所以i=0和j=0的情况不能参与我们关系式的运算,这些元素需要单独拿出来处理,而且这两种元素都是处于二维数组的第一排和第一列的。根据移动只能向下或者向右的特点,我们可以知道,
dp[0][j] = d[0][j-1] + grid[0][j];
dp[i][0] = dp[i-1][0]+grid[i][0];
将整个过程结束之后,dp[m-1][n-1]即为从左上角到右下角,路径总和最小的值。
public int uniquePaths(int m, int n) {
if (m <=0 || n <= 0)
return 0;
int[][] dp = new int[m][n];
for (int i = 0;i < m;i ++)
dp[i][0] = 1; for (int i = 0;i < n;i ++) dp[0][i] = 1; for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = dp[i-1][j] + dp[i][j-1]; } } return dp[m-1][n-1]; }
题目来源:力扣第64题:https://leetcode-cn.com/problems/minimum-path-sum/