前往
大廳
主題

LeetCode - 316. Remove Duplicate Letters 解題心得

Not In My Back Yard | 2021-08-10 00:00:03 | 巴幣 2 | 人氣 744

題目連結:


題目意譯:
給定一字串 s ,移除掉一些字母使得每種字母最多只出現一次。你必須保證你的結果應為所有可能的結果中的字典序最小的。

限制:
1 ≦ s.length ≦ 10 ^ 4
s 由小寫英文字母組成。
 



範例測資:
範例 1:
輸入: s = "bcabc"
輸出: "abc"

範例 2:
輸入: s = "cbacdcbc"
輸出: "acdb"


解題思維:
我們先掃過 s 並找到其中每種字元在 s 中的最後出現位置 P(即最靠近右側的位置)。例如 s = "bcabc" ,P['a'] = 2 、 P['b'] = 3 、P['c'] = 4 (索引值從 0 開始)。

因此當我們掃過 s 中的每個位置 s[i] 時,如果發現 i < P[s[i]],則代表著在 i 之後至少還有一個同 s[i] 之字母存在。因此如果我們要捨棄掉 s[i] ,至少我們還有 s[P[s[i]]] 的存在。

此時我們利用一個堆疊 ST(Stack)來「盡量」維護使得堆疊中的元素從底部到頂端為非嚴格遞增(也就是讓內部元素「盡量」照字典序排列),以及另一個布林陣列 H 來儲存每個字母是否已經存在於 ST 中。

接著我們掃過每個 s[i] 。先判斷 H[s[i]] 是否為真,即 s[i] 是不是已經被挑過了。如果被挑過了就跳過這個字母繼續到下一個。

如果 H[s[i]] 為假,且如果 ST 非空且 ST 的頂端(ST.top())大於 s[i] 且再加上 i < P[ST.top()] 的話,則代表我們可以捨棄掉 ST.top() 這個字元使字典序變小(記得將 H[ST.top()] 設回為假,因為 ST.top() 這個字母現在沒有被挑著)。因為後面在 P[ST.top()] 這個位置時還可以把該字母挑回來。重複此步驟直到條件不符合為止。

接著我們就可以將 s[i] 放到 ST 的頂端,並將 H[s[i]] 設為真,代表我們現在挑了 s[i] 。

如此一來,我們便可以在盡量讓字典序最小的情況下挑到每種字母。因此最後,掃完字串 s 後的堆疊 ST 中,從底部到頂端的元素之序列即為所求。




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

創作回應

更多創作