代码训练(21)LeetCode之跳跃游戏2
Author: Once Day Date: 2025年6月4日
漫漫长路,才刚刚开始...
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
文章目录
-
-
- 代码训练(21)LeetCode之跳跃游戏2
-
- [1. 原题](#1. 原题)
- [2. 分析](#2. 分析)
- [3. 代码实现](#3. 代码实现)
- [4. 总结](#4. 总结)
-
1. 原题
给定一个长度为
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.length <= 104
0 <= nums[i] <= 1000
- 题目保证可以到达
nums[n-1]
示例 1:
yacas
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
示例 2:
yacas
输入: nums = [2,3,0,1,4]
输出: 2
2. 分析
这个问题是一个非常典型的贪心算法问题。我们需要找到从数组的起点到终点的最小跳跃次数。
贪心算法的选择:
- 我们需要在每一步选择能跳得最远的位置,这样可以保证使用最少的跳跃次数。
- 使用两个变量
end
和farthest
分别记录每一次跳跃的结束位置和在这次跳跃中能达到的最远位置。
如何处理:
- 遍历数组,对于每个位置,更新这次跳跃能达到的最远位置
farthest
。 - 如果遍历到了
end
所指示的位置,表明完成了一次跳跃,更新end
为farthest
,跳跃次数加一。
分析步骤:
-
初始化
end
和farthest
为0,跳跃次数jumps
为0。 -
遍历数组中的每个元素,更新能跳到的最远位置
farthest = max(farthest, i + nums[i])
。当索引
i
等于end
,即达到跳跃的边界时:如果
i
不是最后一个元素,则更新end
为farthest
,跳跃次数jumps
加一。如果已经是最后一个元素,结束循环。
-
返回跳跃次数
jumps
。
性能优化关键点
- 时间复杂度:O(n),因为我们只需要遍历数组一次。
- 空间复杂度:O(1),使用了常数个额外空间。
3. 代码实现
c
#include <stdio.h>
int jump(int* nums, int numsSize) {
int end = 0, farthest = 0;
int jumps = 0;
for (int i = 0; i < numsSize - 1; i++) {
farthest = (i + nums[i] > farthest) ? i + nums[i] : farthest;
if (i == end) {
end = farthest;
jumps++;
}
}
return jumps;
}
int main() {
int nums[] = {2, 3, 1, 1, 4};
int numsSize = sizeof(nums) / sizeof(nums[0]);
int result = jump(nums, numsSize);
printf("Minimum jumps required: %d\n", result);
return 0;
}
这段代码实现了"跳跃游戏2"(Jump Game)问题的解决方案,使用贪心策略。
4. 总结
这个问题考察了对贪心算法的理解和应用。通过局部最优解的迭代,达到全局最优解,是贪心算法的核心思想。了解和熟练掌握贪心算法可以帮助解决很多看似复杂的问题,提升算法设计和问题解决能力。