LeetBook刷题笔记011:跳跃游戏(Java实现)
题目
给你一个非负整数数组 nums ,你最初位于数组的第一个位置
数组中的每个元素代表你在该位置可以跳跃的最大长度
你的目标是使用最少的跳跃次数到达数组的最后一个位置
假设你总是可以到达数组的最后一个位置
自己的解:动态规划
- 参考别人的解进行优化过
public int jump(int[] nums) {
//提前获取字符串长度提高效率
int n = nums.length;
//直接返回小长度字符串的唯一情况
if(n<3)
return n==1?0:1;
//定义dp数组:dp[n]表示到达索引n使用的最少步数
int[] dp = new int[n];
//记录nums[j]大于等于i的最小的j索引
int start = 0;
//初始化dp数组(小范围的唯一情况)
dp[0]=0;
dp[1]=1;
for(int i=2;i<n;i++){
//从上次第一个跳跃范围能到i的索引值start开始(提高效率)
for(int j=start;j<i;j++){
//每次判断当前索引元素是否能跳跃到当前i索引
//取j最小的索引(此时跳跃步数最少)直接跳出循环
if(nums[j]>=i-j){
start = j;
//跳到索引i,更新dp数组
dp[i]=dp[j]+1;
break;
}
}
}
return dp[n-1];
}
最优解:反向贪心
- 从终点向原点遍历数组,每次取能跳跃到当前位置的最小索引同时记录步数,直到到达原点
public int jump(int[] nums) {
//记录当前位置,初始为终点
int position = nums.length - 1;
//记录步数
int steps = 0;
//不断遍历直到到达原点
while (position > 0) {
//从原点到当前位置取最小索引
for (int i = 0; i < position; i++) {
if (i + nums[i] >= position) {
//更新当前位置
position = i;
steps++;
break;
}
}
}
return steps;
}
//时间复杂度:O(n^2)
最优解:正向贪心
- 从原点遍历整个数组,每次更新可到达的最远区间,每次区间扩大则添加步数
public int jump(int[] nums) {
int length = nums.length;
//记录上一最远区间
int end = 0;
//记录当前最远区间
int maxPosition = 0;
//记录步数
int steps = 0;
for (int i = 0; i < length - 1; i++) {
//获取在上一最远区间内所能更新的最远区间边界
maxPosition = Math.max(maxPosition, i + nums[i]);
//每次到达上一最远区间边界则更新当前最远区间边界
//由于遍历了所有的上一最远区间内的所有元素的跳跃距离
//更新的当前最远区间边界一定是第二步所能跳跃的最远距离
if (i == end) {
end = maxPosition;
steps++;
}
}
return steps;
}