携手创作,共同成长!这是我参与「掘金日新计划 · 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;
}