1654. 到家的最少跳跃次数

目录

跳蚤跳跃问题:带约束的最短路径搜索详解

题目描述

题目难点与分析

解题思路

状态定义

状态转移

约束判断

限制搜索范围

代码实现(Python)

复杂度分析

示例说明

小结与拓展


跳蚤跳跃问题:带约束的最短路径搜索详解

题目描述

假设有一只跳蚤,它的家在数轴上的某个位置 x。跳蚤从位置 0 出发,目标是跳到它的家。跳跃规则如下:

  • 跳蚤可以向前跳恰好 a 个位置(往右跳)。
  • 跳蚤可以向后跳恰好 b 个位置(往左跳)。
  • 不能连续两次向后跳
  • 跳蚤不能跳到 forbidden 数组中指定的位置。
  • 跳蚤可以跳出它家的位置(即可以跳过 x),但不能跳到负数的位置。

给定整数数组 forbidden,表示跳蚤不能跳到的位置,以及整数 a、b、x,请返回跳蚤跳到 x 的最少跳跃次数。如果无法到达,返回 -1。


题目难点与分析

本题是一个带有复杂约束的最短路径搜索问题:

  • 状态限制:跳蚤不能连续两次往后跳,这限制了跳跃的连续模式。
  • 禁止跳跃位置forbidden 数组给定了禁止跳跃的位置,跳到这些位置无效。
  • 空间范围限制:数轴是无限的,跳蚤可以跳出 xx,但不能跳到负数,搜索范围不确定。
  • 多状态变量:不仅要考虑当前位置,还要考虑上一次跳跃是否为后跳。

这些因素使得简单的 BFS 直接用位置做状态不够,需要额外状态信息来判断“是否连续后跳”。


解题思路

状态定义

(pos, back) 来表示跳蚤的状态:

  • pos 表示当前跳蚤所在位置
  • back 是布尔值,表示跳蚤上一次是否刚后跳(True 表示是后跳,False 表示非后跳)

状态转移

从状态 (pos, back) 可以跳跃到:

  • 向前跳:跳到 pos + a,后退状态设为 False
  • 向后跳:如果上一次不是后跳 (back == False),则可以跳到 pos - b,后退状态设为 True

约束判断

  • 新位置不能是 forbidden 中的点
  • 新位置不能小于 0
  • 跳跃次数最小,因此采用 BFS 遍历,保证首次到达目标即为最短跳跃次数。

限制搜索范围

理论上,跳蚤可以无限向前跳,为防止搜索空间过大,我们定义一个最大边界 limit

limit=max⁡(max⁡(forbidden)+a+b,x+b)

即最大禁止位置附近再多跳几个单位,或目标位置附近稍作缓冲。


代码实现(Python)

from collections import deque

class Solution:
    def minimumJumps(self, forbidden: list[int], a: int, b: int, x: int) -> int:
        forbidden_set = set(forbidden)
        limit = max(max(forbidden, default=0) + a + b, x + b)
        
        # BFS 队列元素格式:(位置, 是否刚后跳, 跳跃次数)
        queue = deque([(0, False, 0)])
        visited = set([(0, False)])  # 记录访问状态,避免重复
        
        while queue:
            pos, back, steps = queue.popleft()
            
            # 到达目标
            if pos == x:
                return steps
            
            # 向前跳
            forward = pos + a
            if forward <= limit and forward not in forbidden_set and (forward, False) not in visited:
                visited.add((forward, False))
                queue.append((forward, False, steps + 1))
            
            # 向后跳(仅当上一步不是后跳)
            backward = pos - b
            if not back and backward >= 0 and backward not in forbidden_set and (backward, True) not in visited:
                visited.add((backward, True))
                queue.append((backward, True, steps + 1))
        
        return -1

复杂度分析

  • 时间复杂度
    搜索范围被限制为 limit,最多访问每个位置两次(后退状态 True 或 False),所以时间复杂度约为 O(limit)。
  • 空间复杂度
    需要存储访问状态和 BFS 队列,空间复杂度也为 O(limit)。

示例说明

假设输入:

forbidden = [14, 4, 18, 1, 15]
a = 3
b = 15
x = 9
  • 起点是0,目标9
  • forbidden禁止跳的点包括1,4,14,15,18
  • 跳跃规则:前跳3步,后跳15步,且不能连续后跳

BFS遍历过程(简化):

  • 起点0,后退状态False,步数0
  • 可以向前跳到3,向后跳不可行(会到负数)
  • 从3开始,向前跳6,向后跳0(不连续后退条件满足)
  • 从6开始,向前跳9(达目标),完成

最短跳跃次数为3次。


小结与拓展

  • 本题典型应用了 BFS 寻找带额外状态的最短路径问题。
  • 需要额外状态记录来解决“不能连续后跳”的限制。
  • 通过合理限定搜索边界,有效避免爆炸搜索空间。
  • 代码实现中,使用集合 visited 存储 (位置, 是否后跳) 状态,保证了 BFS 的正确性与效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值