题目
给定一个长度为 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:
输入: nums = [2,3,0,1,4] 输出: 2
思路:
贪心算法思路
我们需要跟踪当前能到达的最远距离,以及在每一步需要的跳跃次数。具体步骤如下:
-
初始设置:
jumps
计数器,记录跳跃次数。current_end
,表示当前跳跃的最远边界。farthest
,表示在当前范围内能到达的最远位置。
-
遍历数组:
- 循环遍历每个位置,更新
farthest
为当前能到达的最远位置。 - 当遍历到
current_end
时,进行一次跳跃,更新current_end
为farthest
。
- 循环遍历每个位置,更新
-
停止条件:
- 一旦
current_end
到达或超过最后一个索引,返回跳跃次数。
- 一旦
贪心代码:
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size()==1){
return 0;
}
int current_end=0;
int fartherest=0;
int jmp=0;
for(int i=0;i<nums.size();i++){
fartherest=max(nums[i]+i,fartherest);//更新能到达的最远位置
if(i==current_end){
jmp++;
current_end=fartherest;
}
if(current_end>=nums.size()-1){
break;
}
}
return jmp;
}
};
动态规划思路:
-
初始化:
- 创建一个数组
dp
,其长度与nums
相同,用于存储到达每个索引的最小跳跃次数。 dp[0]
初始化为0
,因为从起点到起点不需要跳跃。
- 创建一个数组
-
填充 dp 数组:
- 遍历数组
nums
,对于每个位置i
,计算可以跳跃到的所有位置j
(从i
到i + nums[i]
),更新dp[j]
的值为dp[i] + 1
(从i
跳到j
)。 - 需要确保
j
没有超出数组的边界。
- 遍历数组
-
结果:
- 最后返回
dp[n - 1]
,即到达最后一个位置的最小跳跃次数。
- 最后返回
dp代码:
class Solution {
public:
int jump(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n,std::numeric_limits<int>::max());
if(n<=1)return 0;
dp[0]=0;
for(int i=0;i<n;i++){
for(int j=1;j<=nums[i];j++){
if(i+j<n){
dp[i+j]=min(dp[i+j],dp[i]+1);
}
}
}
return dp[n-1];
}
};