1. 程式人生 > 實用技巧 >80跳躍遊戲 IV(1345)

80跳躍遊戲 IV(1345)

作者: Turbo時間限制: 1S章節: 寬度優先搜尋

晚於: 2020-08-26 12:00:00後提交分數乘係數50%

截止日期: 2020-09-02 12:00:00

問題描述 :

給你一個整數陣列 arr ,你一開始在陣列的第一個元素處(下標為 0)。

每一步,你可以從下標 i 跳到下標:

i + 1 滿足:i + 1 < arr.length

i - 1 滿足:i - 1 >= 0

j 滿足:arr[i] == arr[j] 且 i != j

請你返回到達陣列最後一個元素的下標處所需的最少操作次數 。

注意:任何時候你都不能跳到陣列外面。

示例 1:

輸入:arr = [100,-23,-23,404,100,23,23,23,3,404]

輸出:3

解釋:那你需要跳躍 3 次,下標依次為 0 --> 4 --> 3 --> 9 。下標 9 為陣列的最後一個元素的下標。

示例 2:

輸入:arr = [7]

輸出:0

解釋:一開始就在最後一個元素處,所以你不需要跳躍。

示例 3:

輸入:arr = [7,6,9,6,9,6,9,7]

輸出:1

解釋:你可以直接從下標 0 處跳到下標 7 處,也就是陣列的最後一個元素處。

示例 4:

輸入:arr = [6,1,9]

輸出:2

示例 5:

輸入:arr = [11,22,7,7,7,7,7,7,7,22,13]

輸出:3

輸入說明 :

首先輸入陣列arr的長度n,

然後輸入n個整數,以空格分隔。

1 <= n <= 5 * 10^4

-10^8 <= arr[i] <= 10^8

輸出說明 :

輸出一個整數,表示到達陣列最後一個元素的下標處所需的最少操作次數

輸入範例 :

輸出範例 :

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;

class Solution 
{
public: int minJumps(vector<int>& arr) { int len=arr.size(); vector<int> dis(len,INT_MAX); vector<int> visited(len,0) ;//標記是否被訪問 queue<int> q; unordered_map<int,vector<int>> m; for(int i=0;i<len-1;i++) m[arr[i]].push_back(i); q.push(len-1); dis[len-1]=0; while(!q.empty()) { int front =q.front(); q.pop(); if(front-1>=0&&!visited[front-1]&&m.find(arr[front-1])!=m.end()) { dis[front-1]=min(dis[front-1],dis[front]+1); visited[front-1]=1; q.push(front-1); } if(front+1<len&&!visited[front+1]&&m.find(arr[front+1])!=m.end()) { dis[front+1]=min(dis[front+1],dis[front]+1); visited[front+1]=1; q.push(front+1); } if(m.find(arr[front])!=m.end()) { for(int it:m[arr[front]]) { if(!visited[it]) { visited[it]=1; dis[it]=min(dis[front]+1,dis[it]); q.push(it); } } m.erase(arr[front]);//不加就會超時, 去掉標記過的,訪問過的值直接清理掉 } } return dis[0]; } }; int main() { vector<int> arr; int n,data; cin>>n; for(int i=0; i<n; i++) { cin>>data; arr.push_back(data); } int result=Solution().minJumps(arr); cout<<result; return 0; } /* https://leetcode-cn.com/problems/jump-game-iv/solution/wei-shi-yao-bfsyi-ji-zen-yang-on-by-tian-ye/ 題目要求計算從第一個元素跳到最後一個元素最少的操作次數。首先容易想到的是,座標位於最後一個元素時,結果應為0,因為不用任何操作;對於這個元素緊挨著的左右元素(此時只存在左邊的元素),它的運算元是1,因為只需要跳一次就跳到了最後;同理,對於數組裡值和最後一個元素相等的那些數,他們的運算元都是1。 然後,對於倒數第二個元素,它的運算元前一步已經求得為1,它右邊數的結果也已經知道了,是0;它左邊的數如果不等於最後一個數,那麼它跟最後一個數的距離應為2。這裡距離的意思是指操作次數,即跳兩次才能到達最後一個數;同樣,和倒數第二個數相等的那些元素最小的運算元也都是1+1=2. 這樣,可以理解為最後一個數所在層數為0,第1層就是挨著它的元素以及值和它相等的那些數,第2層就是第一層挨著的元素以及值和第一層元素相等的那些數...按層次依次往上加。因為題目要求最少運算元,對於“挨著它的元素”如果前面已經求出了距離(層數),這時就不用再去算了,因為+1之後結果只會更大。例如,用一個數組dis[]表示每一個元素對應的最小運算元,初始化一個大數,如果對於元素i它左邊有dis[i-1]等於這個大數,就表明i-1位置還沒有求,於是dis[i-1]=dis[i]+1;如果dis[i-1]不等於這個大數就說明左邊的元素前面已經算過了,就不要再去給它+1。 為了去找陣列中和某一個數相等的所有元素位置,使用HashMap來存下所有值和相應位置(列表)的對映,可以避免一遍遍遍歷這個陣列去尋找。 (這時候你就可以自己動手去寫了,小總結:一個數組存結果,一個Map對映和一個佇列來廣度優先搜尋) 現在寫出的程式碼執行那幾個試例是沒問題的,不過提交的時候會遇到一個滿頁是7,最後一個數是13的測例,可能會超時。這裡還可以繼續優化:對於那堆7,從倒數第二個元素開始其實就已經算出了他們的距離是[2,2,...,2,1,0],每次他都會把新出現的7放入佇列,然後又遍歷一遍7所在的所有位置。於是可以用一個數組visited[]來記錄這個數是否被訪問(計算)過,如果已經訪問過了就沒必要再去map裡遍歷它對應的所有位置了。 作者:tian-ye 連結:https://leetcode-cn.com/problems/jump-game-iv/solution/wei-shi-yao-bfsyi-ji-zen-yang-on-by-tian-ye/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。*/