中等
给定一个长度为 n
的 0 索引整数数组 nums
。初始位置为 nums[0]
。
每个元素 nums[i]
表示从索引 i
向前跳转的最大长度。换句话说,如果你在 nums[i]
处,你可以跳转到任意 nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]
。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2从下标为 0 跳到下标为 1 的位置,跳 1步,然后跳 3步到达数组的最后一个位置。
最开始以为是回溯法,结果超时了,因为我理解成最终要恰好到达,而题意是最后一步可以超出末尾的,看答案意思是要保证每一步跳最多,局部最优达到整体最优,以一次跳为一个单元。
第一轮终点范围:
2 3 1 1 1 4
第二轮起点范围:
2 3 1 1 1 4
第二轮终点范围:
2 3 1 1 1 4
第三轮起点范围(第二轮起点末尾->第二轮终点末尾):
2 3 1 1 1 4
每一轮起点的开始是上一轮起点的末尾,因为只有比上一轮起点远才有走下去的意义,而起点的末尾是上一轮能到达的最远地方。
class Solution {
public:
int jump(vector<int>& nums) {
int end=1;//控制起点的最大值
int start=0;//控制起点
int step=0;//记录步数
while(end<nums.size()){
int MaxPos=0;
for(int i=start;i<end;i++){
MaxPos=max(MaxPos,nums[i]+i);
}
start=end;
end=MaxPos+1;
step++;
}
return step;
}
};
只有当走下一步时,才需要更新起点,因此可以进行优化
class Solution {
public:
int jump(vector<int>& nums) {
int end=0;
int MaxPos=0;
int step=0;
for(int i=0;i<nums.size()-1;i++){
MaxPos=max(MaxPos,nums[i]+i);
if(i==end){
end=MaxPos;
step++;
}
}
return step;
}
};