LeetCode第45题思悟——跳跃游戏(jump-game-ii)

LeetCode第45题思悟——跳跃游戏(jump-game-ii)

知识点预告

  1. 贪心思想;
  2. 去冗余的分析意识;

题目要求

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例

示例:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

最常见的思路是从0出发,然后在能力范围内不断跳跃,直到跳到最后;这样的思路下,该问题可以使用递归的方法处理;但是实际上,这是一种暴力解法:访问完所有可能的结果并计算出最优结果;以下为该思路的一个实现,运行超时,倒在最后一个测试用例上;

private int[] buffer;
public int jump(int[] nums) {
	if(nums.length==1){
		return 0;
	}
	buffer=new int[nums.length];
	return jumpHelper(nums,0);
}
private int jumpHelper(int[] nums,int start){
	if(buffer[start]!=0){
		return buffer[start];
	}
	if(nums[start]+start>=nums.length-1){
		buffer[start]=1;
		return 1;
	}//从start到end只需要1次跳跃即可
	int minTimes=Integer.MAX_VALUE;
	boolean hasArrived=false;
	int tempTimes;
	int nextStart;
	int capacity=nums[start];
	for(int i=1;i<=capacity;i++){
		nextStart=start+i;
		if(nextStart<nums.length) {
			tempTimes = jumpHelper(nums, nextStart);
			if(tempTimes!=-1&&minTimes>tempTimes){
				minTimes=tempTimes;
				hasArrived=true;
			}
		}else{
			break;
		}
	}
	if(hasArrived) {
		buffer[start] = minTimes + 1;
		return minTimes + 1;
	}else{
		return -1;
	}
}

优秀解法

//解法A
public int jump(int[] nums) {
	int step = 0;
	int right = 0;
	int cur = 0;
	while (right < nums.length-1) {
		int newRight = right;
		while (cur <= right) {
			newRight = Integer.max(nums[cur] + cur, newRight);
			cur++;
		}
		right = newRight;
		step++;
	}
	return step;
}
//解法B
public int jump(int[] nums){
	int next_r=nums[0];
    int numsSize=nums.length;
	int r=next_r;
	int jump=0;
	for(int i=1;i<numsSize;i++){
		if(--next_r<nums[i]){
			next_r=nums[i];
		}
		if(i==r||i==numsSize-1){
			jump++;
			r+=next_r;
		}
	}
	return jump;
}

差异分析

解法A和解法B思路是一样的;如果要想尽可能快得到达终点,那么每一步跳跃后,下一步跳跃能达到的位置要尽可能的远;为了找到这个点,我们需要遍历完当前跳跃所能覆盖范围内的点;

递归解法之所以超时,是因为,对于每个点,该方法都进行了跳跃尝试,而这些点能不能产生最小跳跃值并不是在达到终点时才能得到——通过计算就能得到选择该点作为落脚点时,下一跳最远可到的位置;

算法之所以不好,一定是做了无用功——对最后结果没有贡献的计算(不用做,但是却做了);

当我们看到题目后,有可能会马上想到解决方法;此时就要对题目进行深入的理解,看能否简化自己的方法,判断自己方法中对题目有贡献的是那些,没有贡献的是那些;如何保留,如何剔除;

本题生动体现了“走一步,看一步”的智慧,而这用比较专业的术语解释即为:贪心算法;贪心解法的正确性是需要逻辑推理和证明的;所以,编程和数学紧密相关;

知识点小结

  1. 贪心思想;
  2. 去冗余的分析意识;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值