LeetCode刷题191119
博主渣渣一枚,刷刷leetcode给自己瞅瞅,大神们由更好方法还望不吝赐教。题目及解法来自于力扣(LeetCode),传送门。
算法:
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
二狗脑子不好使。我的思路大致是这样,从倒数第二位逆序检查数组,如果存在这样的值-----这个值的索引index + 1 +这个值 》= 整个数组的长度,那么从index这个值是肯定可以走到结尾的,也就是说可以返回true了。 这样有一个问题,就是我们可能找到多个这样的index。这里其实只要取最小值就可以了。因为如果能从【0】走到后面的满足条件的index,也一定能走到最小的这个index。
这样我们就可以稍微优化一下,也就是说从index=0开始找,一直循环整个数组,如果我们发现了满足条件的index,就可以缩短整个数组的长度,然后递归的查找。如果最终index为0了,我们就能确定这样的数组是满足条件的。上代码:
public class _55 { public bool CanJump(int[] nums) { if (nums.Length <= 1) { return true; } return Check(nums); } private bool Check(int[] nums) { var index = -1; for (int i = 0; i < nums.Length-1; i++) { if (i + 1 + nums[i] >= nums.Length && i <= nums.Length-2) { index = i; break; } } if (index == -1 || index + 1 > nums.Length) { return false; } else if (index == 0) { return true; } else { return Check(nums.Take(index + 1).ToArray()); } } }
然而,很不幸,上面的代码实在太low了。一是花费了很多精力处理边界情况与返回的结果,不优雅。二是被最后的测试用例[1,1,1,1,1,.........很多很多个1....1,1,1,1,1,]直接干趴下了,运行超时。还是不能随意用递归呀。即使不超时,时间复杂度也高的吓人。
看完了low的解法,我们来瞅一个不low的。年兄的解法:
LeetCode 55: 跳跃游戏
题目内容
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4] 输出: true 解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。 示例 2:
输入: [3,2,1,0,4] 输出: false 解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
本题的解题关键在于,重新理解一遍题目,忽视题目中的跳跃两个字,一步一步走,因为无论如何,你都必须遍历一遍数组才能了解所有的信息,所以“跳跃”是没有意义的。
除了路要一步一步走,每次只走一格,还有饭要一口一口吃。假想每个格点的值就是几口饭,一口饭供你走一格,也就符合了题目描述每个元素代表你在该位置可以跳跃的最大长度。
下面就很简单了,每当你走到下一个格点,你就要做一个决定,是用身上剩下的几口饭继续走下去,还是用新格点的这几口饭走下去。当然是选多的那个。
所以解题思路就是这样的:
首先,你的坐标index位于起点0,元素值temp为起点的值nums[0]。之后每走一步index+1,元素值temp-1,然后进行判断,当前元素值temp和现在坐标index的元素值nums[index]谁大,选择大的那个为新的temp。当temp减到0时,无法继续前进,如果尚未到达终点,则失败。否则成功。
代码如下:
class Solution { public boolean canJump(int[] nums) { int temp = nums[0]; int index = 0; while (index < nums.length-1 && temp >= 0) { if (temp < nums[index]) { temp = nums[index]; } index += 1; temp -= 1; } if (temp < 0) { return false; } else { return true; } } }
这个算法效率理论上是最高的,时间复杂度为数组长度,空间复杂度为常数。结果非常好,应该是最快的了。