小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
跳跃游戏
题目
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
来源:力扣(LeetCode)
思路
-
对于在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];
}