mengjian-github / leetcode

leetcode前端题目笔记

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

45. 跳跃游戏 II

mengjian-github opened this issue · comments

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

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

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

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

 

示例 1:

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

输入: nums = [2,3,0,1,4]
输出: 2

一个直观的想法是利用回溯算法暴力求解:

/**
 * @param {number[]} nums
 * @return {number}
 */
var jump = function(nums) {
    let result = Infinity;
    
    function backtrack(sum = 0, index = 0) {
        if (index >= nums.length - 1) {
            // 找到一个
            if (index === nums.length - 1) {
                result = Math.min(result, sum);
            }
            return;
        }

        let j = nums[index];

        while (j > 0) {
            // 跳j步
            if(index + j <= nums.length) {
                sum++;
                backtrack(sum, index + j);
                // 回溯
                sum--; 
            } 
            
            j--;
        }
    }

    backtrack();

    return result;
};

但是暴力算法无法通过LeetCode

此题可使用贪心算法完成:
每次跳动的距离,选择跳动后再跳一次最远的那一个

/**
 * @param {number[]} nums
 * @return {number}
 */
var jump = function(nums) {
    let result = 0;

    let i = 0;

    while(i < nums.length - 1) {
        let jump = nums[i];
        let choose = jump;
        while (jump > 0) {
            if (i + jump >= nums.length - 1) {
                // 可以直接跳出去
                choose = jump;
                break;
            }

            // 选择jump到达的地方
            const jumpTarget = nums[i+jump] + i+jump;
            const chooseTarget = nums[i+choose] + i+choose;

            if (jumpTarget > chooseTarget) {
                choose = jump;
            }
            
            jump--;
        }

        // 做出新选择
        result++;
        i += choose;
    }
    
    return result;
};