每日算法:动态规划(不同路径、不同路径Ⅱ、最小路径和、爬楼梯)第一天打卡

题目一:不同路径

一个机器人位于一个 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 和 的值均不超过 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]。

发布了135 篇原创文章 · 获赞 98 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/weixin_44588495/article/details/105309434