前往
大廳
主題

LeetCode - 581. Shortest Unsorted Continuous Subarray 解題心得

Not In My Back Yard | 2023-03-16 15:12:52 | 巴幣 0 | 人氣 183

題目連結:


題目意譯:
給定一整數陣列 nums,你需要找到一個連續子陣列使得如果你將這個子陣列按照升序排列後,則整個陣列變成按照升序排列。
 
回傳滿足這樣條件的最短子陣列之長度。

限制:
1 ≦ nums.length ≦ 10 ^ 4
-10 ^ 5 ≦ nums[i] ≦ 10 ^ 5

進階:你可以用 O(n) 的時間複雜度內解出本題嗎?



範例測資:
範例 1:
輸入: nums = [2,6,4,8,10,9,15]
輸出: 5
解釋: 你需要將 [6, 4, 8, 10, 9] 按照升序排列使得整個陣列按照升序排列。

範例 2:
輸入: nums = [1,2,3,4]
輸出: 0

範例 3:
輸入: nums = [1]
輸出: 0


解題思維:
可以看到我們想要求的東西為以下:
找到最小的索引值 L 使得其存在一索引值 i 滿足 L < i 且 nums[L] > nums[i]、
找到最大的索引值 R 使得其存在一索引值 j 滿足 j < R 且 nums[j] > nums[R]。
而 nums[L] ~ nums[R] 即是所求應排序的最短子陣列,其長度為 R - L + 1。

而要找到 L 只需要使用我們的老朋友——堆疊(Stack)(其實用雙端佇列(Deque)也可以)來維護「非嚴格遞增性」即可(參見這題)。

也就是說,假設現在堆疊內的元素從底端到頂端是非嚴格遞增的(即小到大,但數字可以重複)。此時如果有一個新的數字要進來的話,則我們可以從頂端開始移除數字直到頂端不大過新數字為止(或是到堆疊為空為止),這樣便可以維持「非嚴格遞增性」。

這樣有什麼好處呢?我們仔細看的話,實際上過程中被移除掉的頂端數字,它們的索引值即是 L 的候選者(即滿足「存在一索引值 i 滿足 L < i 且 nums[L] > nums[i]」之條件)。

而這些候選者最小者即為 L 本身。

因此我們只需要從左至右掃過一次 nums,期間維護堆疊的「非嚴格遞增性」即可找到 L。

同理,R 也可以用類似的方式找到,即從右至左掃過 nums,期間維護堆疊的「非嚴格遞減性」(因為我們把 nums 反過來看了)即可。



最後的所求即為 R - L + 1;不過有可能找不到 L 和 R,此時代表著 nums 本來就已經排序好了,因此所求為 0。




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作