力扣练习——24 去除重复字母
1.问题描述
给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入: "bcabc"
输出: "abc"
示例 2:
输入: "cbacdcbc"
输出: "acdb"
2.输入说明
输入一个仅包含小写字母的字符串
3.输出说明
输出结果。首尾无多余空格或空行。
4.范例
输入
cbacdcbc
输出
acdb
5.代码
#include<iostream> #include<vector> #include<string> #include<algorithm> using namespace std; string removeDuplicateLetters(string s) { //题目要求: //去除字符串中重复的字母,使得每个字母只出现一次 //需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 //解题思路: //1.首先是根据字典序排序,所以贪心的思想 //2.由于相对顺序不能变,因此需要在保证每个字母至少出现一次的前提下再考虑字典序 //3.利用单调栈来保证字典序列(从小到大),单调栈:非递增或者非递减栈。 //4.栈顶元素出栈条件要进行限制,只有在栈非空 且 栈顶元素的字典序排在目前遍历的新元素之后 且 栈顶元素在之后还会出现时 ,出栈 //1.申明变量 vector<int>num(26, 0);//注意这里的初始化方法,统计a~z的字母出现的次数,初始值全为0 vector<bool>exist(26, false);//用来统计栈中是否存在该元素 //2.统计每个字符出现次数 for (int i = 0; i < s.size(); i++) num[s[i] - 'a']++; //3.遍历字符串,进行入栈与出栈操作 string ans = "";//利用这个模拟栈 for (int i = 0; i < s.size(); i++) { if (!exist[s[i] - 'a'])//没有在栈中存在过 { //重点理解下面部分代码 栈顶元素为ans.back() //栈不为空 && 栈顶元素字典序靠后 && 栈顶元素还有剩余出现次数 while (ans.size()!=0 && ans.back()>s[i] && num[ans.back()-'a']>0 ) { exist[ans.back() - 'a'] = false;//修改出现状态 ans.pop_back();//出栈 } ans.push_back(s[i]);//该位置字母压栈 exist[s[i] - 'a'] = true;//修改出现状态 } num[s[i]-'a']--;//每遍历一个字母,该字母出现次数减一 } return ans; } int main() { string s; cin >> s; string res = removeDuplicateLetters(s); cout << res; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理