小知识,大挑战!本文正在参与“ 程序员必备小知识 ”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
3. 跳跃游戏 II
问题:
给定一个非负整数数组,你最初位于数组的第一个位置。数组的每个元素代表你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置。
解法1:反向查找出发位置 我们的目标是到达数组的最后一个位置,因此我们可以考虑最后一步跳跃前所在的位置,该位置通过跳跃能够到达最后一个位置。 如果有多个位置通过跳跃都能够到达最后一个位置,那么我们应该如何进行选择呢?直观上来看,我们可以「贪心」地选择距离最后一个位置最远的那个位置,也就是对应下标最小的那个位置。因此,我们可以从左到右遍历数组,选择第一个满足要求的位置。找到最后一步跳跃前所在的位置之后,我们继续贪心地寻找倒数第二步跳跃前所在的位置,以此类推,直到找到数组的开始位置。
class Solution {
public:
//用一个dp记录到当前位置的最小跳跃次数,然后从投开始去更新次数!
int jump(vector<int>& nums) {
int n =nums.size();
int position=n-1;
int step=0;
while(position>0)
{
for(int i=0;i<n-1;i++)
{
if(i+nums[i]>=position)
{
step++;
position=i;
break;
}
}
}
return step;
}
};
最坏情况下O(n2)的复杂度,会超时。 解法1:从前往后,按照步数贪心的去找。 本质和跳跃问题1一样。从哪个当前位置出发,用一个值记录能够跳跃的最远距离,然后在索引小于这个最远距离前,不断遍历,去更新下一步可能的最远距离。 如果下一步的最远距离大于末尾,则停止,返回step+1。
// class Solution {
// public:
// //
// int jump(vector<int>& nums) {
// int n =nums.size();
// int position=n-1;
// int step=0;
// while(position>0)
// {
// for(int i=0;i<n-1;i++)
// {
// if(i+nums[i]>=position)
// {
// step++;
// position=i;
// break;
// }
// }
// }
// return step;
// }
// };
class Solution {
public:
//正向去找当前跳跃次数最大的边界。 一定要先理清楚逻辑
int jump(vector<int>& nums) {
int n =nums.size();
if(n==1) return 0; // 单独考虑出来
int now_max_pos=nums[0];
int next_max_pos=nums[0];
int step=1;
if(now_max_pos>=n-1) return step;
for(int i=1;i<n-1;i++)//边界,不需要最后一个元素。
{
if(i<=now_max_pos)
{
next_max_pos = max(next_max_pos,i+nums[i]);//step+1步中的最大边界
if(next_max_pos>=n-1) return ++step;
}
if(i==now_max_pos)//这个时候才更新
{now_max_pos = next_max_pos; step++;}
}
return step;
}
};