两道关联题目,跳跃游戏,两道都没顺利做出来,好好记录一下。
55 跳跃游戏
题目描述
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
解题思路
这道题的核心是判断能否的到达最后的位置。一开始我的想法是每次跳的时候找到达范围内能够跳最远的,可是我混淆了一个条件,就是数组的每个元素表示的是从当前位置出发能够去的步数,需要加上这个位置的下标才是到达的最远步数,所以一开始死活都过不了,一个最经典的测试用例就是[4, 2, 0, 0, 1, 1, 4, 4, 0, 1]
,前面半段[4, 2, 0, 0, 1]
的时候代码错误选了2
就以为没发到达最后位置。
代码如下:
class Solution:
def canJump(self, nums: List[int]) -> bool:
i = 0
lns = len(nums)
if lns == 1:
return True
max_length = 0
while i < lns:
if i <= max_length:
# 寻找最远的位置
max_length = max(max_length, i + nums[i])
if max_length >= lns - 1:
return True
i += 1
return False
45 跳跃游戏 ii
这个换了一种思路,假设一定能去到,就看要最短多少步。
题目描述
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
示例 2:
输入: nums = [2,3,0,1,4]
输出: 2
解题思路
还是和55一样,寻找最远的位置,不同的地方在于维护一个边界,在遍历过程中,更新最远可以到达的位置,到达边界的时候,更新边界为最远可以到达的位置,并且更新边界为新的最远可以到达的位置。
有个地方需要注意的是:并不是真的让你跳,而是把数组元素挨个遍历一遍就OK
另外就是:只需要遍历到倒数第二个元素就可以了,因为题目已经保证肯定能到,遍历到最后一个元素的话会造成无效跳跃,多了一次。
class Solution:
def jump(self, nums: List[int]) -> int:
lns = len(nums)
if lns == 1:
return 0
i = 0
# max_pos 为可以到达的最远位置
max_pos, end = 0, 0
res = 0
for i in range(lns - 1):
if max_pos >= i:
# 当前的数据点在最远位置距离内
max_pos = max(max_pos, i + nums[i])
# 到达边界更新边界为最远可以到达的位置
if i == end:
end = max_pos
res += 1
return res