【题目】
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
示例 1:
输入: nums = [2,3,1,1,4]
输出: true
解释: 可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入: nums = [3,2,1,0,4]
输出: false
解释: 无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
提示:
1 <= nums.length <= 10^40 <= nums[i] <= 10^5
【题目解析】
解题方法
- 始化一个变量
max_reach记录当前能到达的最远位置。 - 遍历数组,对于每个位置
i,更新max_reach为max(max_reach, i + nums[i])。 - 如果在某次遍历中
i超过了max_reach,说明存在一个位置无法被到达,返回false。 - 如果
max_reach大于等于数组的最后一个下标,则返回true。
class Solution:
def canJump(self, nums: List[int]) -> bool:
max_reach = 0 # 最远能到达的位置
for i, jump in enumerate(nums):
if i > max_reach:
# 如果当前位置超过了之前能到达的最远位置,返回False
return False
max_reach = max(max_reach, i + jump) # 更新最远能到达的位置
if max_reach >= len(nums) - 1:
# 如果能到达或超过最后一个位置,返回True
return True
return max_reach >= len(nums) - 1
执行效率
【总结】
适用问题类型
贪心算法适用于那些通过每一步的局部最优选择,能够达到全局最优解的问题。在跳跃游戏问题中,通过在每个位置做出“跳得尽可能远”的局部最优决策,我们可以判断是否能够到达数组的末端,这正是贪心算法应用的典型场景。
解决算法:贪心算法
-
算法描述:在遍历数组的过程中,维护一个变量
max_reach来记录当前能够到达的最远位置。对于每一个位置i,如果它在max_reach范围内,更新max_reach为max(max_reach, i + nums[i])。最终,如果max_reach大于等于数组的最后一个位置,说明可以到达最后;否则,不可以。 -
算法特点:
- 简洁高效:贪心算法通过一次遍历就能得出是否能够到达数组末尾的结论。
- 无需额外空间:算法运行过程中仅使用有限的几个变量,不需要额外的数据结构。
- 易于理解和实现:算法逻辑清晰,代码简洁。
时间复杂度与空间复杂度
- 时间复杂度:
O(n)。算法只需要遍历数组一次,其中n是数组nums的长度。 - 空间复杂度:
O(1)。除了输入数组之外,算法只需要常数级别的额外空间。
实践意义
- 解决范围广泛的优化问题:贪心算法的实践意义不仅局限于跳跃游戏这一问题,它适用于许多需要找到最优解决方案的场景,如资源分配、调度问题等。
- 算法设计思维的培养:通过理解和应用贪心算法解决问题,开发者可以培养出一种寻找并利用问题局部最优解以达到全局最优的思维方式。
- 编程技能的提升:贪心算法的应用可以帮助提升算法设计和实现的技能,特别是在处理复杂数据结构和算法问题时,能够快速准确地找到高效解决方案。
总之,跳跃游戏问题通过贪心算法的解决方案不仅展示了算法的强大能力,也为解决更广泛的优化问题提供了思路和方法。掌握这种算法,对于提高编程能力和解决实际问题都具有重要的意义。