1.題目
題目地址(316. 去除重複字母 - 力扣(LeetCode))
https://leetcode.cn/problems/remove-duplicate-letters/
題目描述
給你一個字串 s
,請你去除字串中重複的字母,使得每個字母只出現一次。需保證 返回結果的
示例 1:
輸入:s = "bcabc"
輸出:
"abc"
示例 2:
輸入:s = "cbacdcbc"
輸出:"acdb"
提示:
1 <= s.length <= 104
s
由小寫英文字母組成
注意:該題與 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同
2.題解
2.1 單調棧+
思路
程式碼
- 語言支援:C++
C++ Code:
class Solution {
public:
string removeDuplicateLetters(string s) {
vector<int> nums(26), vis(26);
// 初始化各元素初始個數
for(char ch : s){
nums[ch - 'a']++;
}
// 貪心+單調棧解決字串去重問題
string stk; // 跳出固有思維, 單調棧是一種演算法思維,並不一定非要使用棧
for(char ch : s){
// 如果當前字元尚未被訪問
if(!vis[ch - 'a']){
// 保證單調棧從棧頂到棧底遞減(小的字元在棧底,保證位元組序小), 當前字元小於棧頂就彈出棧頂
while(!stk.empty() && ch < stk.back()){
// 如果剩餘字元數量足夠,就彈出
if(nums[stk.back() - 'a']){
vis[stk.back() - 'a'] = 0; // 更新為未訪問狀態
stk.pop_back(); // 彈出
} else{
break;
}
}
// 找到當前字元應有的入棧位置
stk.push_back(ch);
vis[ch - 'a'] = 1; // 更新訪問標誌
}
// 如果當前字元訪問過則不入棧, 但還是要更細剩餘數量,所以將兩種情況合二為一
nums[ch - 'a']--;
}
return stk;
}
};
複雜度分析
令 n 為陣列長度。
- 時間複雜度:\(O(n)\)
- 空間複雜度:\(O(n)\)