前端算法(38)

94 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

题目解析

思路一

我们可以记录每走一步所能到达的最远位置,作为下一步的终点,起点为当前位置的下一位置,起点到终点为下一步的起始位置,获取下一步能达到的最远位置,以此类推,直到当前步骤最远位置可达终点

var jump = function(nums) {
  let start = 0, // 第 n 轮起点
      end = 0, // 第 n 轮终点,len+1 可作为 n+1 轮的起点
      maxPos = 0, // 第 n 轮所能到达的最远位置,可作为 n+1 轮的终点
      ans = 0 // 记录当前是第几轮,为已走步数
  while(end < nums.length-1) {
    // 从起点到终点,计算当前轮下一步能达到的最远位置
    for(let i=start; i<= end; i++) {
      maxPos = maxPos >  i+nums[i] ? maxPos : i+nums[i]
    }
    // 下一轮起点为当前轮+1
    start = end + 1
    // 下一轮为当前轮所能达到的最远位置
    end = maxPos
    // 步数计算
    ans ++
  }
  return ans
};

思路二

/**
 * @param {number[]} nums
 * @return {number}
 */
var jump = function(nums) {
    if(nums.length <=1) return 0
    //将一开始所在的第一步添加进去
    let res = [nums[0]]
    let lastStepIndex = 0
    while(res[res.length-1] < nums.length-1-lastStepIndex){
        // 上一步能走的总步数
        let steps = res[res.length-1]
        // 预备节点:下一步能走的最远的位置,至少要大于上一步能走的步数
        let newMaxStepIndex = lastStepIndex
        for(let i= 1;i<=steps;i++){
            // 这里的i为:从上一个记录点到现在所走的步数
            // 当前这一步的Index
            let curIndex = i + lastStepIndex
            // 当前这一步能走的步数
            let curSteps = nums[curIndex]
            /* 
                i+curSteps :从上一个记录点到现在已经走了的步数 + 当前节点能走的步数
                nums[newMaxStepIndex] + (newMaxStepIndex - lastStepIndex):预备记录点能走的步数 + 上一个记录点至预备节点之间的步数,注意这里并不是拿已经走了的步数i去加预备节点的步数,因为当前的i已经超过了预备节点所在的位置
             */
            if(i+curSteps > nums[newMaxStepIndex] + (newMaxStepIndex - lastStepIndex)){
                newMaxStepIndex = curIndex
            }
        }
        res.push(nums[newMaxStepIndex])
        lastStepIndex = newMaxStepIndex
    }
    return res.length
};