你有一個長度爲 n 的隊伍,從左到右依次爲 1~n,有 m 次插隊行爲,用數組 cutIn 進行表示,cutIn 的元素依次表明想要插隊的人的編號,每次插隊,這我的都會直接移動到隊伍的最前方。你須要返回一個整數,表明這 m 次插隊行爲以後,有多少我的已經不在原來隊伍的位置了。數組
輸入:3,[3, 2, 3]數據結構
輸出:2spa
說明:code
初始隊伍爲 [1, 2, 3]blog
3 開始插隊 [3, 1, 2]ip
2 開始插隊 [2, 3, 1]it
3 開始插隊 [3, 2, 1]io
因此2還在原來的尾置,3和1兩我的已經不在原來的位置了。class
先來看一個例子15 [10, 4, 6, 5, 9, 7, 3, 3, 9, 10],咱們來模擬一下插隊過程。遍歷
第一次:10
第二次:4 10
第三次:6 4 10
第四次:5 6 4 10
第五次:9 5 6 4 10
第六次:7 9 5 6 4 10
第七次:3 7 9 5 6 4 10
第八次:3 7 9 5 6 4 10
第九次:9 3 7 5 6 4 10
第十次:10 9 3 7 5 6 4
最終位置:10 9 3 7 5 6 4 1 2 8 11 12 13 14 15
能夠發現,隊伍最終的排列是由最後一次插隊決定的,而後沒插隊的人所有依次排在插隊的人的後面。所以從後往前遍歷cutIn數組,遇到重複的跳過。
判斷是否還在原位置時,將隊伍分爲兩部分計算:插隊的人和沒插隊的人。對於插隊的人,直接判斷位置和序號是否匹配;設插隊的人中最大序號爲max,對於沒插隊的人,序號>max的必定還在原來隊伍中的位置,<max的必定不在原來位置(結合生活實際,很好理解:咱們在排隊的時候,不太關心排在本身前面的人的位置變更,由於這不會影響到咱們本身的等待時間,可是一旦排在本身後面的人插到本身前面,咱們就會很不爽,由於這會形成本身的等待時間邊長)
題目讓求有多少我的已經不在原來隊伍的位置,咱們能夠逆向思惟計算有多少人還在原來的位置,而後減去這個值就能獲得位置改變的總人數。
下圖展現了例子中隊伍的判斷狀況:
tips:
Set、HashMap等數據結構均可以處理重複值。HashMap的key值是編號這個沒問題,對於value類型的選擇,我直接用true/false來記錄是否訪問過;也可使用Integer來記錄編號爲key的人在隊伍中的最終位置。其實仔細觀察會發現咱們全程並不關心value值是多少(咱們是經過map.containsKey()來判斷是否重複的),也就是說HashMap徹底能夠退化成Set,不過實際提交代碼時發現使用HashMap的程序運行時間更短,因此下面的代碼仍是用HashMap了。
public class Solution { /** * 計算有多少我的最終不在本身原來的位置上 * @param n int整型 隊伍總長 * @param cutIn int整型一維數組 依次會插隊到最前方的人的編號 * @return int整型 */ public int countDislocation (int n, int[] cutIn) { if(cutIn.length == 0) return 0; HashMap<Integer, Boolean> visited = new HashMap<>(); int max = 0, same = 0, number = 1; for(int i = cutIn.length - 1; i >= 0; i--) { if(!visited.containsKey(cutIn[i])) { visited.put(cutIn[i], true); if(cutIn[i] == number++) same++; max = Math.max(max, cutIn[i]); } } return max - same; } }