时间轴
时间轴
2025-10-02
init
贪心,动态规划
题目:
我最先想到的是动态规划令 dp[i] 表示到达 i 的最小跳跃次数,-1 表示不可达,那么对于 0 <= j < i,如果 j 可以到达 i ,即 nums[j] + j >= i 且 dp[j] != -1
如果没有可达的 j 那么
123456789101112131415161718192021222324252627282930313233 | using std::vector;class Solution {public: int jump(vector<int> &nums) { // dp[i]表示到达i的最小跳跃次数,-1表示不可达 // 对于 0<=j <i // if(nums[j] + j >= i ) dp[i] = dp[j] + 1; // 如果不存在这样的j,dp[i] = -1; int n; int min; n = nums.size(); vector<int> dp(n, -1); dp[0] = 0; for (int i = 1; i < n; i++) { min = INT_MAX; for (int j = 0; j < i; j++) { if (nums[j] + j >= i && dp[j] != -1 && dp[j] + 1 < min) { min = dp[j] + 1; } } if (min != INT_MAX) { dp[i] = min; } else { dp[i] = -1; } } return dp[n - 1]; }}; |
这道题其实是经典的贪心题,从后往前看,最后一个位置一定是之前某个位置跳过来的,但是这个之前的位置可能有多个,那么我们就贪心地选择最远的那个(因为反正都是多一步,选择离起点更近的必定能减少跳跃次数,这因为如果两个点都能到达最后一个位置,a 的位置靠前,b 的位置靠后,那么我们肯定会选择 a,因为到达 a 的 step 必定小于等于 b 的 step)。选择后,选择的这个位置就成了新的最后一个位置。
123456789101112131415161718 | class Solution {public: int jump(vector<int>& nums) { int position = nums.size() - 1; int steps = 0; while (position > 0) { for (int i = 0; i < position; i++) { if (i + nums[i] >= position) { position = i; steps++; break; } } } return steps; }}; |
也可以用下面这道题的思路改造
官方题解:
如果我们「贪心」地进行正向查找,每次找到可到达的最远位置,就可以在线性时间内得到最少的跳跃次数。
例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。
从下标 1 出发,最远可到达下标 4。下标 1 可到达的位置中,下标 4 的值是 4 ,从下标 4 出发可以达到更远的位置,因此第二步到达下标 4。

在具体的实现中,我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。
在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。
123456789101112131415161718192021 | class Solution {public: int jump(vector<int>& nums) { int i = 0, j = 0, n = nums.size(); int max_pos = 0; int last_end = 0; int step = -1; for(i = 0; i< n;i++){ max_pos = std::max(max_pos, i + nums[i]); if(i == last_end){ last_end = max_pos > n-1 ? n-1: max_pos; step++; } } return step; }}; |
leetcode hot 100 rewrite
1234567891011121314151617181920212223242526 | using std::vector;class Solution { public: int jump(vector<int> &nums) { // 从后往前跳,贪心地选择最远的那个能跳过来的 int i, n = nums.size(); int curr = n - 1; int cnt = 0; while (curr > 0) { for (i = 0; i < curr; i++) { if (nums[i] + i >= curr){ curr = i; cnt++; break; } } } return cnt; }}; |
