leetcode 316 去除重複字母
題目大意:
給你乙個字串\(s\),請你去除字串中重複的字母,使得每個字母只出現一次。需保證返回結果的字典序最小(要求不能打亂其他字元的相對位置)。
題解:
參考自leedcode官方題解
首先考慮乙個簡單的問題:給定乙個字串\(s\),如何去掉其中的乙個字元\(ch\),使得得到的字串字典序最小呢?答案是:找出最小的滿足\(s[i]>s[i+1]\)的下標\(i\),並去除字元\(s[i]\)。為了敘述方便,下文中稱這樣的字元為「關鍵字元」。
在理解這一點之後,就可以著手本題了。乙個直觀的思路是:我們在字串\(s\)中找到「關鍵字元」,去除它,然後不斷進行這樣的迴圈。但是這種樸素的解法會建立大量的中間字串,我們有必要尋找一種更優的方法。
我們從前向後掃瞄原字串。每掃瞄到乙個位置,我們就盡可能地處理所有的「關鍵字元」。假定在掃瞄位置\(s[i-1]\)之前的所有「關鍵字元」都已經被去除完畢,在掃瞄字元\(s[i]\)時,新出現的「關鍵字元」只可能出現在\(s[i]\)或者其後面的位置。
於是,我們使用單調棧來維護去除「關鍵字元」後得到的字串,單調棧滿足棧底到棧頂的字元遞增。如果棧頂字元大於當前字元\(s[i]\),說明棧頂字元為「關鍵字元」,故應當被去除。去除後,新的棧頂字元就與\(s[i]\)相鄰了,我們繼續比較新的棧頂字元與\(s[i]\)的大小。重複上述操作,直到棧為空或者棧頂字元不大於\(s[i]\)。
我們還遺漏了乙個要求:原字串\(s\)中的每個字元都需要出現在新字串中,且只能出現一次。為了讓新字串滿足該要求,之前討論的演算法需要進行以下兩點的更改。
在考慮字元\(s[i]\)時,如果它已經存在於棧中,則不能加入字元\(s[i]\)。為此,需要記錄每個字元是否出現在棧中。
在彈出棧頂字元時,如果字串在後面的位置上再也沒有這一字元,則不能彈出棧頂字元。為此,需要記錄每個字元的剩餘數量,當這個值為\(0\)時,就不能彈出棧頂字元了。
class solution
string ans;
for (char ch : s) else
}vis[ch - 'a'] = true;
ans.push_back(ch);
}num[ch - 'a']--;
}return ans;
}};
leetcode316 去除重複字母
給你乙個字串 s 請你去除字串中重複的字母,使得每個字母只出現一次。需保證 返回結果的字典序最小 要求不能打亂其他字元的相對位置 首先記錄每個元素出現的最後位置。然後建立乙個棧和乙個集合。若當前字元已經在集合 現過了,則跳過該字元 反之,如果棧頂元素大於當前字元,且棧頂元素的最後出現位置在當前位置之...
leetCode 316 去除重複字母
給你乙個字串 s 請你去除字串中重複的字母,使得每個字母只出現一次。需保證 返回結果的字典序最小 要求不能打亂其他字元的相對位置 注意 該題與 1081 相同 示例 1 輸入 s bcabc 輸出 abc 示例 2 輸入 s cbacdcbc 輸出 acdb 先要明白如果在乙個字串中刪去乙個字元需要...
Leetcode 316 去除重複字母
很典型的一道單調棧題目class solution char stack newchar 26 棧頂指標 int top 1 for int i 0 i n i 退棧 如果棧非空 並且 棧的頭元素大於目前元素 並且 棧的頭元素剩餘個數不為0 進行退棧操作 while top 0 stack top ...