力扣练习——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;
}
复制代码

 

posted @   努力奋斗的小企鹅  阅读(76)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示