题目描述
[45. 跳跃游戏 II]
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
示例 1:
输入: nums = [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2。 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。 示例 2:
输入: nums = [2,3,0,1,4] 输出: 2
提示:
1 <= nums.length <= 104 0 <= nums[i] <= 1000
题解
此题到手,我一时没想到思路,不过做算法题,永远要相信一点的就是:思路比做题重要!
首先要想到一种方案,能讲得通的方案,然后再根据这个方案去实现算法,这样才会有方向,否则就像一只无头苍蝇在窗户上乱撞,也找不到出口。 这题的最重要的一句就是:假设你总是可以到达数据的最后一个位置。那这句的意思就是:假如我站的索引位置i,可以用当前数据num[i]
或者当前数据num[i]
以下的次数跳出去,就算成功了。这句用开发语言表达出来就是:
var l = num.length
if(i+num[i] >= l)
game is over ! biu biu biu
复制代码
此时问题又来了,到这一步我是结束了,问题我是走了多少步才到这里的呢?也就是这是一个倒推的算法,首先想到了最后的一个结果状态,然后再根据这个成功的状态去反推前面的过程,这就是顺瓜摸藤的解法思路。不过这不是学名,学名应该叫贪心算法,找到一个局部最优解,然后实现破局。
前面我们已经有了一个最后一步的算法,现在反过来想,既然最后一步已经安排好了,我们是不是可以不考虑最后一步了,直接把后面的掐掉,考虑前面的那部分,思路跟这个一样,也是先找最后一步,这样一步步推上去,就把步数算出来了。
好了,思路我已经分析好了,具体写法就按照思路来,中间肯定会遇到问题,多试几次就出来了。
直接上代码吧,掐后面不用真的掐,只有设卡点就好了,然后注意索引不要错位,细节在自己写的时候自己体会吧!
/**
* @param {number[]} nums
* @return {number}
*/
var jump = function(nums) {
var position = nums.length - 1;
var steps = 0;
while (position > 0) {
for (var i = 0; i < position; i++) {
if (i + nums[i] >= position) {
position = i;
steps++;
break;
}
}
}
return steps
};
复制代码
复杂度分析
- 时间复杂度:O(n²),还好,大部分情况下n会掉的比较快
- 空间复杂度: O(1)