跳跃游戏 IV —— 区间跳跃判断能否到达终点
题目描述
给定一个下标从 0 开始的二进制字符串 s 和两个整数 minJump 和 maxJump。初始位置在下标 0,且 s[0] 一定是 '0'。
你可以从当前位置 i 跳跃到位置 j,满足以下条件:
- 跳跃距离符合:
i + minJump <= j <= min(i + maxJump, s.length - 1) s[j] == '0',即目标位置必须是'0'
请判断是否存在一条跳跃路径,可以从位置 0 跳到位置 s.length - 1。
解题分析
这个问题的核心是判断是否存在一条合法的跳跃路径,跳跃的范围是一个闭区间 [minJump, maxJump],每次跳跃只能跳到值为 '0' 的位置。问题本质上是图的遍历问题:
- 节点:字符串中的每个位置。
- 边:从位置
i到[i+minJump, i+maxJump]范围内满足s[j] == '0'的节点。
直接思路
- 使用 BFS 或 DFS 遍历:
- 从 0 开始,遍历所有符合跳跃条件的节点。
- 记录已访问节点,避免重复搜索。
- 但是直接枚举区间
[i + minJump, i + maxJump]每次都遍历可能导致时间复杂度过高。
解题方法
方法一:直接 BFS/DFS(不推荐)
简单的 BFS/DFS 遍历,时间复杂度可能是 O(n * (maxJump - minJump)),当 maxJump - minJump 较大时会超时。
方法二:BFS + 区间优化(推荐)
核心思路:
- 使用 BFS 队列保存可以跳到的节点。
- 用一个变量
max_reach记录当前遍历过的最远位置。 - 每次从
i出发,遍历区间[max(i + minJump, max_reach + 1), min(i + maxJump, n - 1)],避免重复访问。 - 只有区间中
s[j] == '0'的位置才入队。 - 一旦到达末尾
n-1返回True。
这种方法避免了大量区间的重复遍历,大幅降低了时间复杂度。
代码实现
from collections import deque
class Solution:
def canReach(self, s: str, minJump: int, maxJump: int) -> bool:
n = len(s)
# 如果起点或终点不是 '0',直接返回 False
if s[0] != '0' or s[-1] != '0':
return False
queue = deque([0])
max_reach = 0 # 记录已访问过的最远位置
while queue:
i = queue.popleft()
# 新的区间开始位置,不重复访问
start = max(i + minJump, max_reach + 1)
# 新区间结束位置
end = min(i + maxJump, n - 1)
for j in range(start, end + 1):
if s[j] == '0':
if j == n - 1:
return True
queue.append(j)
# 更新最远访问位置,防止重复遍历
max_reach = max(max_reach, end)
return False
复杂度分析
- 时间复杂度:
由于每个位置最多被访问一次,且每次只遍历“新增”的区间,整体复杂度约为 O(n),其中 n 是字符串长度。 - 空间复杂度:
队列和额外标记空间最多存储 O(n) 个元素。
示例说明
以示例字符串:
s = "011010"
minJump = 2
maxJump = 3
- 初始位置:0(
s[0] == '0') - 可以跳跃的区间是
[i + 2, i + 3]
遍历过程:
- 从位置 0 出发,可跳到位置 2 或 3:
s[2] == '1',跳过s[3] == '0',加入队列
- 从位置 3 出发,跳跃范围
[5, 6],但字符串长度是 6,最大是位置 5:s[5] == '0',加入队列,且位置 5 是末尾
- 因此可以成功跳到末尾,返回
True
总结
- 该问题用 BFS 搜索跳跃路径,关键是优化跳跃区间避免重复遍历。
- 通过记录
max_reach,只遍历未访问过的新区间,实现了高效搜索。 - 代码简洁且执行效率高,适合处理大规模输入。
1087

被折叠的 条评论
为什么被折叠?



