赞
踩
给定一个长度为 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
1 <= nums.length <= 104
0 <= nums[i] <= 1000
nums[n-1]
先分析题目,跳跃游戏II与跳跃游戏相比更加复杂了一点,跳跃游戏只需要判断能否通过跳跃到达最后一个下标,而跳跃游戏II需要我们计算出跳跃到最后一个下标所需要的最小跳跃次数。对此,我们还是可以采用贪心算法的思想,我们找出每一个下标所能到达的最远位置,从而来找到最远位置是最后一个下标的下标,进而判断出什么时候进行跳跃,同时统计跳跃次数即可。这是对整体的一个构思。从整体构思可以看出我们需要解决两个问题,一个是我们怎么判断是否到了最后一个下标,另一个就是我们怎么去统计跳跃次数。(因为当我们在每一个下标的时候可能会有多种跳跃方案)
首先解决怎么判断是否到最后一个下标,首先题目告诉我们“题目保证可以到达nums[n-1]”,因此不需要我们对其进行判断,而是只需要通过计算来获得最远位置为nunsSize-1。因此我们可以采用for循环的方法,遍历整个数组,依次计算i+nums[i](当前下标所能到达的最远位置)的值,并将其与当下的最远位置进行比较,取较大值。以此不断计算,我们就可以让site=numsSize-1。这样第一个问题解决了。【求每个范围的最远位置,最后找到最后一个下标】
然后第二个问题就是我们怎么去计算这个跳跃次数。当我们在一个下标上的时候,我们会获得一个跳跃范围,也就是下一个下标到所能到达的最远位置下标。那我们怎么去判断什么时候跳跃呢,因为可能我走一步更好,也可能走两步更好,这就是相对于详细的,就是跳跃一次跳跃几步,但我们只需要知道跳跃次数,而对跳跃步数不用管。因而我们只需要知道它什么时候一定要跳跃一次就行。
那当我们可以在一个范围内随意选择跳跃时什么时候我们必须进行跳跃呢?是不是我们到达了这个范围的边界的时候,因为当我们访问到这个范围的边界的时候,这个范围的最远位置我们就已经统计出来了,因此我们肯定会进行跳跃,然后继续更新边界,直至到达最后一个下标。最开始的边界设置为0,因为从第一个下标出来我们必须要跳跃一步(至于跳到了哪个下标我们不知道),然后我们将这个边界更新成目前得到的最远下标,然后继续进行找在这一个范围内所能到的最远位置【局部最优解】,因为我们不需要知道具体跳跃到了哪个下标,所以我们以每个范围的边界为条件来计算跳跃次数,一旦到达边界则次数增加,直至到达最后一个下标,则结束,如此就能够得到最小次数。
实际上就是一个不断扩大范围的过程,直至将范围扩大至最后一个下标,在这个过程中,有几次到达边界就意味着跳跃了几次。
①定义最小跳跃次数num,范围边界end,最远位置site变量
②定义max函数用来更新最远位置
③遍历数组更新最远位置并计算跳跃次数
④返回跳跃次数
- int max(int x,int y){
- return x>y?x:y;
- }
- int jump(int* nums, int numsSize){
- int num = 0;//达到nums[n-1]的最小跳跃次数
- int end = 0;//用来标志所能到达的最远边界
- int site=0;//能到达的最远位置
- for (int i = 0; i < numsSize-1; i++)
- {
- //通过遍历来找出每一个下标所能跳跃到的最远位置,取最远的
- site = max(site,i+nums[i]);
- //如果已经遍历到了所能到达的范围的边界,此时必须进行一次跳跃,同时更新所能到达的范围的边界
- if (i == end)
- {
- end = site;
- num++;
- }
- }
- return num;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。