跳跃游戏&最小路径和(动态规划)

275 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

跳跃游戏

题目

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

 

来源:力扣(LeetCode)

思路

  1. 对于在i位置上面,能够跳跃的范围为i+nums[i],那么对于能够跳跃到的那些位置选择一个性价比最高的(跳跃之后能够跳的更远的点)

2.一旦发现i+nums[i]>=nums.length - 1直接返回true;

3.如果发现某个位置已经无法继续向下跳跃了,直接返回false

代码

public class Code30_CanJump {
    public static void main(String[] args) {
        int[] arr = {2,3,1,1,4};
        Code30_CanJump c30 = new Code30_CanJump();
        System.out.println(c30.canJump(arr));
    }

    public boolean canJump(int[] nums) {

        return process(nums, 0);
    }

    public boolean process(int[] nums, int idx) { //idx表示当前所在的下标
        if (nums[idx] >= nums.length - 1 - idx) return true;
        //选择性价比最高的进行跳跃
        int target = idx + nums[idx];
        int targetIdx = idx;
        for (int i = idx; i <= idx + nums[idx]; i++) {
            if (nums[i] + i > target) { //跳跃
                target = nums[i] + i;
                targetIdx = i;
            }
        }
        if (target == nums[idx] + idx) return false; //没有变化
        return process(nums, targetIdx);

    }
}

最小路径和

题目

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明: 每次只能向下或者向右移动一步。

思路

1.一个比较简单的二维的动态规划,dp[i][j]表示到达i行j列的最小路径和

2.先对i=0和j=0的情况进行处理,这样在两层for循环的时候就不需要加额外的判断了

3.这边有递归版和动态规划版的代码,递归版超时了,可以通过递归推出动态规划

代码

递归版

public int minPathSum(int[][] grid) {
    int m = grid.length - 1;
    int n = grid[0].length - 1;
    return process(grid, m, n);


}

public int process(int[][] grid, int i, int j) {
    int res = grid[i][j];
    if (i == 0 && j == 0) { //到达
        return grid[0][0];
    }
    res += Math.min(i - 1 < 0 ? Integer.MAX_VALUE : process(grid, i - 1, j), j - 1 < 0 ? Integer.MAX_VALUE : process(grid, i, j - 1));
    return res;
}

动态规划版



public int minPathSumDp(int[][] grid) {
    int m = grid.length;
    int n = grid[0].length;
    int[][] dp = new int[m][n];
    dp[0][0] = grid[0][0];
    for (int i = 1; i < m; i++) {
        dp[i][0] += dp[i - 1][0] + grid[i][0];
    }
    for (int j = 1; j < n; j++) {
        dp[0][j] += dp[0][j - 1] + grid[0][j];
    }
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
        }
    }
    return dp[m - 1][n - 1];
}