跳跃游戏 贪心算法

问题

给定一个非负数组,数组中的元素代表从当前位置可以向后跳几步,判断能否走到数组末尾。例如:A = [2,3,1,1,4], return true;A = [3,2,1,0,4], return false.

贪心算法实现方式

/**
 * 给定一个非负数组,数组中的元素代表从当前位置可以向后跳几步,判断能否走到数组末尾。
 * 例如:{ 1, 1, 1, 1, 0 } { 1, 1, 2, 0, 0 } return true;{ 3, 2, 1, 0, 0 } { 2, 0, 0, 2, 0 } return false
 */
public static boolean canJump(int[] nums) {
	final int MAX_INDEX = nums.length - 1;//代表数组最后一个元素的下标
	int maxJumpIndex = nums[0];//定义这个变量是关键!它代表的是当前已知的、最远能跳到的、数组元素的下标(即最远能够跳到的位置)
	for (int i = 0; i <= maxJumpIndex; i++) {//注意,这里遍历结束的条件有两个,一个是 i > maxJumpIndex时,即逐个遍历完数组所有元素后
		maxJumpIndex = Math.max(maxJumpIndex, i + nums[i]);//【贪心算法】这一行代码运用的就是著名的贪心算法
		if (maxJumpIndex >= MAX_INDEX) return true;//第二个遍历结束的条件在这里,即当我最远能够跳到的位置包含数组最后一个元素时
	}
	return false;//如果以上遍历过程中没有return true,那就return false
}

x

1

/**

2

 * 给定一个非负数组,数组中的元素代表从当前位置可以向后跳几步,判断能否走到数组末尾。

3

 * 例如:{ 1, 1, 1, 1, 0 } { 1, 1, 2, 0, 0 } return true;{ 3, 2, 1, 0, 0 } { 2, 0, 0, 2, 0 } return false

4

 */

5

public static boolean canJump(int[] nums) {

6

 final int MAX_INDEX = nums.length - 1;//代表数组最后一个元素的下标

7

 int maxJumpIndex = nums[0];//定义这个变量是关键!它代表的是当前已知的、最远能跳到的、数组元素的下标(即最远能够跳到的位置)

8

 for (int i = 0; i <= maxJumpIndex; i++) {//注意,这里遍历结束的条件有两个,一个是 i > maxJumpIndex时,即逐个遍历完数组所有元素后

9

  maxJumpIndex = Math.max(maxJumpIndex, i + nums[i]);//【贪心算法】这一行代码运用的就是著名的贪心算法

10

  if (maxJumpIndex >= MAX_INDEX) return true;//第二个遍历结束的条件在这里,即当我最远能够跳到的位置包含数组最后一个元素时

11

 }

12

 return false;//如果以上遍历过程中没有return true,那就return false

13

}

问题解析

如果第一个元素能够直接跳到终点,那么整个过程就已经结束了

如果第一个元素不能 直接跳到终点,那我们就需要先跳到中间某一个元素,然后再看这个元素是否能 直接跳到终点

后面的过程完完全全是在一个更小范围内重复前面的过程

但是的一个核心问题是,我们中间那个元素可能有很多种选择,我们应该选择哪一个元素作为中间元素呢?

我们采取的策略是:逐个判断这些能跳到的元素中,接下来谁能跳的更远,我们就选谁作为中间元素!

比如,3 2 1 1... 第1个元素能跳到第2个、第3个、第4个元素

第2个元素最多能跳到第4个元素, 第3个元素最多能跳到第4个元素,第4个元素最多能跳到第5个元素

所以,我们肯定选择第4个元素作为中间元素,因为 第2个、第3个元素能跳到的 元素,第4个元素都能跳到

但是如果是这种情况, 比如,3 4  3 1 ...

此时,第2个元素最多能跳到第6(2+4)个元素, 第3个元素最多能跳到第6(3+3)个元素,第4个元素最多能跳到第5(4+1)个元素

这个时候我们应该选择跳到第2个元素或者第3个元素(这两个是完全是一样的),而不应该选择第4个元素

疑问一:会不会因为这一步选择了当前可以跳的更远的元素,导致最终到不了终点,并且放弃了选择某个可以到达终点的元素?

肯定不会。因为如果能够通过被放弃的某个元素到达终点,通过当前选择的这个元素也能到达终点!

PS:貌似这个解释有点牵强啊!

疑问二:会不会不是最优解?

贪心算法可能不是最优解,但多数情况下是最优解,而这种情况就是最优解。

PS:这个解释更牵强了。

贪心算法简介

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说, 不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法 不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备 无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

贪心选择

贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是 贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们 必须证明每一步所作的贪心选择最终能得到问题的最优解。 通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。

最优子结构

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。 贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

คิดถึง643

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值