Description

A certain bug’s home is on the x-axis at position x. Help them get there from position 0.

The bug jumps according to the following rules:

  • It can jump exactly a positions forward (to the right).
  • It can jump exactly b positions backward (to the left).
  • It cannot jump backward twice in a row.
  • It cannot jump to any forbidden positions.

The bug may jump forward beyond its home, but it cannot jump to positions numbered with negative integers.

Given an array of integers forbidden, where forbidden[i] means that the bug cannot jump to the position forbidden[i], and integers a, b, and x, return the minimum number of jumps needed for the bug to reach its home. If there is no possible sequence of jumps that lands the bug on position x, return -1.

Example 1:

Input: forbidden = [14,4,18,1,15], a = 3, b = 15, x = 9
Output: 3
Explanation: 3 jumps forward (0 -> 3 -> 6 -> 9) will get the bug home.

Example 2:

Input: forbidden = [8,3,16,6,12,20], a = 15, b = 13, x = 11
Output: -1

Example 3:

Input: forbidden = [1,6,2,14,5,17,4], a = 16, b = 9, x = 7
Output: 2
Explanation: One jump forward (0 -> 16) then one jump backward (16 -> 7) will get the bug home.

Constraints:

  • 1 <= forbidden.length <= 1000
  • 1 <= a, b, forbidden[i] <= 2000
  • 0 <= x <= 2000
  • All the elements in forbidden are distinct.
  • Position x is not forbidden.

分析

题目的意思是:给定一个一维的坐标轴,a是每次向前跳的步数,b是每次向后跳的步数,forbidden是不允许跳到的点,问跳到x点的最小步数。这道题需要用递归,我这里分享一下别人的解法。

  1. 无论是 bfs 还是 dfs,都按先右移,再左移的操作,进行递归(dfs) 或者进队(bfs),才能保证能到达目标节点时,步数最少。
  2. 防止无限递归是关键,forbidden 中加入右移时遍历到的数据
  3. forbidden中不能加入左移时遍历到的数据,原因是 因为左移后退回cur-b处时,无法覆盖前进到cur-b再后退到cur-2b的情况。

看完别人的解答后,感觉不难,可能我没经验,哈哈

代码

class Solution:
def minimumJumps(self, forbidden: List[int], a: int, b: int, x: int) -> int:
forbidden=set(forbidden)
Q=deque()
Q.append([0,0,False])
while Q:
cur,cnt,used=Q.popleft()
if(cur==x):
# 第一次到x即最小步数,因为队列后序元素cnt都是大于等于当前cnt的
return cnt
if(cur+a<6000 and cur+a not in forbidden):
# 6000是往右探索的最大值,x最大为2000
forbidden.add(cur+a)
Q.append([cur+a,cnt+1,False])
if(not used and cur-b>0 and cur-b not in forbidden):
# 这里不能forbidden,因为后退回cur-b处时,无法覆盖前进到cur-b再后退到cur-2b的情况。
Q.append([cur-b,cnt+1,True])
return -1

参考文献

​Python3 - BFS 和 DFS解法​