comments | difficulty | edit_url | rating | source | tags | |||
---|---|---|---|---|---|---|---|---|
true |
Medium |
2124 |
Biweekly Contest 39 Q3 |
|
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.
We can use the position and jumping direction of the flea as the state, and use BFS to search for the shortest path. The key point of this problem is to determine the right boundary, that is, how far the flea can jump.
If
If
In summary, we can set the right boundary to
Next, we use BFS to search for the shortest path. We use a queue, initially adding the position and jumping direction of the flea as the state to the queue. Each time we take a state from the queue, if the position of this state is equal to
- Jump forward, the jumping direction is
$1$ ; - When the current jumping direction is
$1$ , jump backward, the jumping direction is$0$ .
Note that we need to judge whether the next state is legal, that is, the position of the next state does not exceed the right boundary, is not in the forbidden position, and has not been visited.
If the queue is empty, it means that the target position cannot be reached, return
The time complexity is
class Solution:
def minimumJumps(self, forbidden: List[int], a: int, b: int, x: int) -> int:
s = set(forbidden)
q = deque([(0, 1)])
vis = {(0, 1)}
ans = 0
while q:
for _ in range(len(q)):
i, k = q.popleft()
if i == x:
return ans
nxt = [(i + a, 1)]
if k & 1:
nxt.append((i - b, 0))
for j, k in nxt:
if 0 <= j < 6000 and j not in s and (j, k) not in vis:
q.append((j, k))
vis.add((j, k))
ans += 1
return -1
class Solution {
public int minimumJumps(int[] forbidden, int a, int b, int x) {
Set<Integer> s = new HashSet<>();
for (int v : forbidden) {
s.add(v);
}
Deque<int[]> q = new ArrayDeque<>();
q.offer(new int[] {0, 1});
final int n = 6000;
boolean[][] vis = new boolean[n][2];
vis[0][1] = true;
for (int ans = 0; !q.isEmpty(); ++ans) {
for (int t = q.size(); t > 0; --t) {
var p = q.poll();
int i = p[0], k = p[1];
if (i == x) {
return ans;
}
List<int[]> nxt = new ArrayList<>();
nxt.add(new int[] {i + a, 1});
if ((k & 1) == 1) {
nxt.add(new int[] {i - b, 0});
}
for (var e : nxt) {
int j = e[0];
k = e[1];
if (j >= 0 && j < n && !s.contains(j) && !vis[j][k]) {
q.offer(new int[] {j, k});
vis[j][k] = true;
}
}
}
}
return -1;
}
}
class Solution {
public:
int minimumJumps(vector<int>& forbidden, int a, int b, int x) {
unordered_set<int> s(forbidden.begin(), forbidden.end());
queue<pair<int, int>> q;
q.emplace(0, 1);
const int n = 6000;
bool vis[n][2];
memset(vis, false, sizeof(vis));
vis[0][1] = true;
for (int ans = 0; q.size(); ++ans) {
for (int t = q.size(); t; --t) {
auto [i, k] = q.front();
q.pop();
if (i == x) {
return ans;
}
vector<pair<int, int>> nxts = {{i + a, 1}};
if (k & 1) {
nxts.emplace_back(i - b, 0);
}
for (auto [j, l] : nxts) {
if (j >= 0 && j < n && !s.count(j) && !vis[j][l]) {
vis[j][l] = true;
q.emplace(j, l);
}
}
}
}
return -1;
}
};
func minimumJumps(forbidden []int, a int, b int, x int) (ans int) {
s := map[int]bool{}
for _, v := range forbidden {
s[v] = true
}
q := [][2]int{[2]int{0, 1}}
const n = 6000
vis := make([][2]bool, n)
vis[0][1] = true
for ; len(q) > 0; ans++ {
for t := len(q); t > 0; t-- {
p := q[0]
q = q[1:]
i, k := p[0], p[1]
if i == x {
return
}
nxt := [][2]int{[2]int{i + a, 1}}
if k&1 == 1 {
nxt = append(nxt, [2]int{i - b, 0})
}
for _, e := range nxt {
j, l := e[0], e[1]
if j >= 0 && j < n && !s[j] && !vis[j][l] {
q = append(q, [2]int{j, l})
vis[j][l] = true
}
}
}
}
return -1
}
function minimumJumps(forbidden: number[], a: number, b: number, x: number): number {
const s: Set<number> = new Set(forbidden);
const q: [number, number][] = [[0, 1]];
const n = 6000;
const vis: boolean[][] = Array.from({ length: n }, () => [false, false]);
vis[0][1] = true;
for (let ans = 0; q.length; ++ans) {
for (let t = q.length; t; --t) {
const [i, k] = q.shift()!;
if (i === x) {
return ans;
}
const nxt: [number, number][] = [[i + a, 1]];
if (k & 1) {
nxt.push([i - b, 0]);
}
for (const [j, k] of nxt) {
if (j >= 0 && j < n && !s.has(j) && !vis[j][k]) {
vis[j][k] = true;
q.push([j, k]);
}
}
}
}
return -1;
}