题目一:不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
示例一:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例二:
输入: m = 7, n = 3
输出: 28
class Solution {
public int uniquePaths(int m, int n) {
int[][] arr = new int[n][m];
for(int i = 0;i < n;i++){
arr[i][0] = 1;
}
for(int i = 0;i < m;i++){
arr[0][i] = 1;
}
for(int i = 1;i < n;i++){
for(int j = 1;j < m;j++){
arr[i][j] = arr[i - 1][j] + arr[i][j - 1];
}
}
return arr[n-1][m-1];
}
}
我觉得这个题也是比较简单吧,一个二维数组就搞定,主要的思想是arr[i][j]表明的是到达这个点有多少种路径方法。再前两个for循环属于初始化,(机器人每次只能向下或者向右移动一步)这句话就很关键!之后遍历一次就可以了。
题目二:不同路径Ⅱ
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
说明:m 和 n 的值均不超过 100。
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int[][] arr = new int[obstacleGrid.length][obstacleGrid[0].length];
arr[0][0] = obstacleGrid[0][0]==1?0:1;
for(int i = 1;i < arr.length;i++){
if(obstacleGrid[i][0] == 1){//遇到障碍物
for(int j = i;j < arr.length;j++){
arr[j][0] = 0;
}
break;
}else{
arr[i][0] = arr[i-1][0];
}
}
for(int i = 1;i < arr[0].length;i++){
if(obstacleGrid[0][i] == 1){//遇到障碍物
for(int j = i;j < arr[0].length;j++){
arr[0][i] = 0;
}
break;
}else{
arr[0][i] = arr[0][i - 1];
}
}
for(int i = 1;i < arr.length;i++){
for(int j = 1;j < arr[0].length;j++){
if(obstacleGrid[i][j] == 1){//遇到障碍物
arr[i][j] = 0;
}else{
arr[i][j] = arr[i - 1][j] + arr[i][j - 1];
}
}
}
return arr[ arr.length-1][arr[0].length-1];
}
}
这个也非常简单,我们定义一个二维数组,arr,arr和题目一的作用是一样的,当我们遇到障碍的时候arr[i][j]就变成了0。初始化第一排和第一列的时候,如果发现有障碍,那么后面的都是0。
题目三:最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
class Solution {
public int minPathSum(int[][] grid) {
for(int i = 1;i < grid.length;i++){
grid[i][0] += grid[i - 1][0];
}
for(int i = 1;i < grid[0].length;i++){
grid[0][i] += grid[0][i-1];
}
for(int i = 1;i < grid.length;i++){
for(int j = 1;j < grid[0].length;j++){
grid[i][j] += Math.min(grid[i - 1][j] , grid[i][j - 1]);
}
}
return grid[grid.length - 1][grid[0].length - 1];
}
}
这个题就更容易一些了,先初始化第一排和第一列,然后呢找grid[i - 1][j]和 grid[i][j - 1]中较小的相加,就意味着到达某一路径中最向下还是向右是路径最小,然后相加。
题目四:爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
class Solution {
public int climbStairs(int n) {
int[] arr = new int[n + 1];
arr[0] = 1;
arr[1] = 1;
for(int i = 2;i <= n;i++){
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}
}
这题应该是非常经典的一个题了,其实就是一个斐波那契数列。这个题也可以用递归搞,但是那样的话就太low了。
思路是这样的,arr[i]表示上第i阶楼梯的时候的方法数。初始化时候arr[0和arr[1]都是1,]。如果要迈上2阶楼梯,可以选择从第一个台阶上一个台阶和直接迈两层。所以arr[2] = arr[0] + arr[1]。如果3阶楼梯,可以是从第二个台阶选择上一个台阶这是一个方法 ,也可以从第一个台阶迈两层,这是第二个方法。所以arr[3] = arr[2] + arr[1]。