力扣-316. 去除重复字母
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)\)