45. 跳跃游戏
链接
https://leetcode.cn/problems/jump-game-ii/description/
思路
最基本的思路,能到达某结点的跳跃方式中,最左边的那个结点是最优的;换句话说,到达左边的结点比到达右边的结点更容易。
所以我们可以写代码模拟,每次都求能达到target_index的最左边结点,直到这个结点的index为0.
但是上述做法需要O(n**2)的时间复杂度。
怎么优化呢。
试想一下,比如[2,3,0,1,4]。从开头开始跳,那么3和0都是我们的可达范围。我们可以计算出第一次跳跃可达范围的结点下一次跳跃的最大可达范围是哪个。
每搜索完一次当前的可达范围,我们就可以更新res(因为res+1代表了必须要跳跃1次,并没有限定死从哪里跳跃,我们从可达范围内必须要跳一次达到下一个可达范围,所以这个逻辑没有问题)。
代码-从右往左找结点
class Solution: def jump(self, nums) -> int: target_idx = len(nums) - 1 res = 0 while target_idx != 0: cur_target_idx = target_idx for i in range(target_idx-1, -1, -1): if nums[i] + i >= target_idx: cur_target_idx = i res += 1 target_idx = cur_target_idx return res
代码-从左往右找结点
class Solution: def jump(self, nums) -> int: target_idx = len(nums) - 1 res = 0 while target_idx != 0: cur_target_idx = target_idx for i in range(target_idx): if nums[i] + i >= target_idx: cur_target_idx = i break res += 1 target_idx = cur_target_idx return res
代码-记录最大可达范围(可认为是dp)
class Solution: def jump(self, nums): res = 0 rightIndex = 0 maxPos = 0 for i in range(len(nums)-1): # 记录下一次跳跃的最大可达范围 maxPos = max(maxPos, i+nums[i]) # 跳到当前可达范围终点 if i == rightIndex: rightIndex = maxPos res += 1 return res