leetcode刷题日记-【45. 跳跃游戏 II】

84 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

题目描述

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

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

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

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

 

示例 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步,求达到数组底部移动的最小次数。
  • 给定的数组既是跳跃条件,也是路径总长度,即路径总长度=nums.length。

解题思路

这道题乍一看,很容易想到回溯算法,但是这道题的难点是每一个节点不是固定跳跃步数,而是最大跳跃步数,所以如果要进行回溯的话,子问题过多 本题要求的是最小的步数,而不是所有最小步数的元素,所以可以用贪心算法

什么是贪心算法呢?

贪心算法一般来讲是将问题拆分成多个子问题,然后对子问题求最优解而不是求整体最优解,所以没办法获取到整体所有最优解。 所以不是所有问题用贪心算法都能获取得到整体最优解,关键是要看贪心策略的选择。贪心策略一定要有无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

贪心算法的步骤:

  • 将求解的问题分解成若干个小问题
  • 对小问题求最优解
  • 将小问题的最优解合并成整体最优解

基础结构:

 while(目标前进) {
      利用可行的决策,求出当前的最优解
  }
 由所有局部最优解合并成全局最优解

代码实现

/**
 *
 * @param nums
 * @return
 */
public static int jump(int[] nums) {
    // 记录最小跳跃次数
    int res = 0;
    // 从数组最末尾开始进行求解,就当前问题分解成求到最后一位的最远的一个元素的位置
    int position = nums.length-1;
    // 目标依次向左移动
    while (position > 0) {
        // 从左向右依次寻找能满足条件的元素
        for (int i = 0;i < position;i ++) {
            if (i + nums[i] >= position) {
                // 第一次满足条件的一定是局部最优解
                position = i;
                // 全局最优解+1
                res ++;
                break;
            }
        }
    }
    return res;
}