题目:力扣https://leetcode-cn.com/problems/jump-game-ii/
class Solution {
public int jump(int[] nums) {
if(nums.length==1){
return 0;
}
return greedAlgorithm(nums);
}
private int greedAlgorithm(int[] nums){
int len = nums.length;
int distance = len-1;
int pedometer = 0;
int i = 0;
int max = 0;
boolean flag = false;
while(true){
max = 0;
int maxValue = -1;
for(int j=0;j<=nums[i];j++){//遍历可以选择的元素
if(nums[i+j]>=distance){//查看是否可能直达目标
flag = true;
if(j!=0 && distance>1){
pedometer++;
}
break;
}
if(nums[i+j]+i+j>=maxValue){//找到最大值的下标(除了自己以外最大的值)
max = i+j;
maxValue = nums[max]+i+j;
}
}
if(flag==false){//暂且不能一步到,选最大值
i = max;
pedometer++;
distance = (len-1)-i;
}else{//一步到达
pedometer++;
break;
}
}
return pedometer;
}
}
思路:这题叫“跳跃游戏II”,按道理应该还有一题叫“leetcode55.跳跃游戏”,可我尚未遇到,等我遇到那题我再补充把。我是使用贪心算法解题,还没看题解,所以代码啰啰嗦嗦一大堆,回头再看看大佬的题解。贪心,顾名思义就是每一次取值都取“收益”最大的元素,这题中的收益就是“跳跃距离”。这题中的收益不仅仅跟每个位置可跳跃距离有关,跟每个位置的下标也有关系。它们二者需要结合起来当作一个指标来考虑。每一次跳远,判断是否能够“一步登天”,若能则按照既定路线一步登天;若不能,则每次都选择收益最大的一步来跳跃。
1.写一个贪心算法的方法,传入题目给定的数组,传出最少的跳跃步数。
private int greedAlgorithm(int[] nums){
//......
}
2.声明一堆变量。len是给定数组长度;distance是实际距离终点的距离;pedometer是计步器,记录跳了多少步;i表示当前位置的下标,默认值为0;max表示收益最大位置的下标,默认值为0;flag表示是否可以“一步登天”的状态,默认值为false;
int len = nums.length;
int distance = len-1;
int pedometer = 0;
int i = 0;
int max = 0;
boolean flag = false;
3.while每循环一次,就是跳了一步,每跳一步都需要重置max(收益最大一步的下标)和maxValue(收益最大时可跳跃的长度),以便后续判断。通过for循环遍历当前可选择的元素,判断当前一步是否有可能“一步登天”。若“脚下”所站的元素的值大于distan或遍历到可选的值大于distance即表示可以一步上岸,则改变信号旗flag的值,则跳出for循环不需要再遍历后面的元素了。若“脚下”所站的元素的值就大于distance,则只需1步;若只是遍历可选元素的值大于distance则需要先跳到该可选元素上再跳到重点,则需要2步,此处应作判断进行分类讨论。
若不能“一步登天”,则判断那一步“收益最大”。收益的计算公式:收益=该位置的值+该位置的下标。遍历完每一个可选择的位置后,得出当前“收益最大”的一步并记录这一步的下标和“收益”,将这个位置作为下一步的起跳位置。
while(true){
max = 0;
int maxValue = -1;
for(int j=0;j<=nums[i];j++){//遍历可以选择的元素
if(nums[i+j]>=distance){//查看是否可能直达目标
flag = true;
if(j!=0 && distance>1){
pedometer++;
}
break;
}
if(nums[i+j]+i+j>=maxValue){//找到最大值的下标(除了自己以外最大的值)
max = i+j;
maxValue = nums[max]+i+j;
}
}
//......
}
4.根据flag的信号,判断是否能够“一步登天”。若flag的值为false,则表示“革命尚未成功,同志仍需努力!”就老老实实更新i的位置,记录好步数pedometer,更新新的离终点距离distance,准备开始下一轮的while循环。若flag的值是true,则表示已经看到“胜利”的曙光了,按部就班的步数加1次,然后直接break跳出while循环。
if(flag==false){//暂且不能一步到,选最大值
i = max;
pedometer++;
distance = (len-1)-i;
}else{//一步到达
pedometer++;
break;
}
5.跳出while循环后,将计步器pedometer作为出参返回。
return pedometer;
6.在主方法中先排除一些“搞事情”的例子(那些只有一个元素的,您就别搁着蹦了,直接返回0。)
if(nums.length==1){
return 0;
}
7.调用greedAlgorithm(),返回该方法传出来的计步器上的值即可。
return greedAlgorithm(nums);