LeetCode 題解 —— 1654. 到家的最少跳躍次數
阿新 • • 發佈:2020-12-09
技術標籤:OJ題解# LeetCode題解LeetCode題解1654BFS
題目相關
題目連結
LeetCode 中國,https://leetcode-cn.com/problems/minimum-jumps-to-reach-home/。
Problem Statement
有一隻跳蚤的家在數軸上的位置 x 處。請你幫助它從位置 0 出發,到達它的家。
跳蚤跳躍的規則如下:
它可以 往前 跳恰好 a 個位置(即往右跳)。
它可以 往後 跳恰好 b 個位置(即往左跳)。
它不能 連續 往後跳 2 次。
它不能跳到任何 forbidden 陣列中的位置。
跳蚤可以往前跳 超過 它的家的位置,但是它 不能跳到負整數 的位置。
給你一個整數陣列 forbidden ,其中 forbidden[i] 是跳蚤不能跳到的位置,同時給你整數 a, b 和 x ,請你返回跳蚤到家的最少跳躍次數。如果沒有恰好到達 x 的可行方案,請你返回 -1 。
Samples 1
輸入:forbidden = [14,4,18,1,15], a = 3, b = 15, x = 9
輸出:3
解釋:往前跳 3 次(0 -> 3 -> 6 -> 9),跳蚤就到家了。
Samples 2
輸入:forbidden = [8,3,16,6,12,20], a = 15, b = 13, x = 11
輸出:-1
Samples 3
輸入:forbidden = [1,6,2,14,5,17,4], a = 16, b = 9, x = 7
輸出:2
解釋:往前跳一次(0 -> 16),然後往回跳一次(16 -> 7),跳蚤就到家了。
資料範圍
- 1 <= forbidden.length <= 1000
- 1 <= a, b, forbidden[i] <= 2000
- 0 <= x <= 2000
- forbidden 中所有位置互不相同。
- 位置 x 不在 forbidden 中。
題解報告
題目分析
LeetCode 官方將本題難度定為中等。讀完題目,本題求最短路徑,哪就可以使用 BFS 了。
難點
難點一
和標準 BFS 相比,本題有一個限制,那就是回跳不能連續兩次。
如何解決這個問題呢?很簡單,記錄一下上次動作。這樣我們就可以判斷了。我們可以定義如下的資料型別。
struct JUMP {
int pos;//位置
bool act;//動作。false為向後跳,true向前跳
JUMP(int _pos, bool _act) : pos(_pos), act(_act) {}
JUMP() { pos=0; act=true; }
};
難點二
在如下的資料
[162,118,178,152,167,100,40,74,199,186,26,73,200,127,30,124,193,84,184,36,103,149,153,9,54,154,133,95,45,198,79,157,64,122,59,71,48,177,82,35,14,176,16,108,111,6,168,31,134,164,136,72,98]
29
98
80
卡了好久。原因是前後是不同的,一個點即可以是往前跳到的,也可以是往後跳到的。不能因為往前跳到了這個點,就不允許這個點以後不讓往後跳到了。
我的控制方法是在向後不控制 visit。這裡目前我也說不出一個所以然,再仔細查查資料。
難點三
也正是由於可以向後跳,使得我們需要控制向前跳的總次數。根據題目可知 x 的最大值是 2000,a 的最大值是 2000,因此 x+2a 是最大的位置,也就是 6000。操作了這個位置,肯定是到不了家的。
AC 參考程式碼
const int MAXN=6e3+4;
int cost[MAXN];
struct JUMP {
int pos;//位置
bool act;//動作。false為向後跳,true向前跳
JUMP(int _pos, bool _act) : pos(_pos), act(_act) {}
JUMP() { pos=0; act=true; }
};
class Solution {
public:
int minimumJumps(vector<int>& forbidden, int a, int b, int x) {
if (0==x) {
return 0;
}
//可見性控制
vector<bool> visit(MAXN, false);
for (int i=0; i<forbidden.size(); i++) {
visit[forbidden[i]]=true;
}
queue<JUMP> q;
q.push(JUMP(0, false));
visit[0]=true;
int cost=0;//價值
while (false==q.empty()) {
cost++;//下一跳價值
int len=q.size();
for (int i=0; i<len; i++) {
//當前位置
JUMP curr=q.front();
q.pop();
//向前跳
int npos=curr.pos+a;
if (npos<MAXN && false==visit[npos]) {
//判斷是不是終點
//合法性判斷
if (x==npos) {
return cost;
}
visit[npos]=true;
//加入佇列
q.push(JUMP(npos, false));
}
//向後跳
npos = curr.pos-b;
//合法性判斷
if (npos>=0 && false==visit[npos] && false==curr.act) {
//合法性判斷
if (x==npos) {
return cost;
}
//visit[npos]=true;
//加入佇列
q.push(JUMP(npos, true));
}
}
}
return -1;
}
};
時間複雜度
O(N)。
空間複雜度
O(N)。