题解 | 去除重复字母

  1. 去除重复字母:原题链接

题意:

     给你一个字符串s,删除字符串中重复的字符,使新字符串的字典序最小(不能打乱字符串原顺序),且原字符串中出现的字符都要有且仅有一个。

做题思路:

     通过题目,我们可以得知想要拿到字典序最小的字符串,只要遍历字符串并用读入,便利点时重复循环:当栈顶的字符大于当前字符时,就删除该字符,直到当前字符不大于栈顶或栈为空时,停止循环。这样就可以得到最小的字典序字符串。

     但题目要求,每个出现在字符串中的字符都要出现一次,所以我们需要对字符串进行统计,当进行删除操作时,判断当前字符位置之后是否还有该字符,如果不存在,则停止删除,结束循环,还存在则继续循环。

     由此可以得出以下代码:

string removeDuplicateLetters(string s) {
    int n=s.size();
    stack<char>q;
    //cnt用以记录字符串个数
    vector<int>cnt(30,0);
    //vis用来标记字符串,判断字符是否被选中
    vector<int>vis(30,0);
    //统计各个字符的个数 
    for (int i=0;i<n;i++)cnt[s[i]-'a']++;
    for (int i=0;i<n;i++)
    {
    	//每次遍历减去当前字符个数 
        cnt[s[i]-'a']--;
        //如果已经选择字符中已经有过该字符则跳过本次循环 
        if (vis[s[i]-'a'])continue;
        /*
        	循环的三个条件含义分别是:
			1.!q.empty():当栈为空时,停止循环,防止越界
			2.s[i]<q.top():当当前字符的大小小于当前字符串的末尾字符时进行循环
			3.cnt[q.top()-'a']:当cnt计数为0时,说明此时该字符之后已经没有相同字符了,必须保留	 
        */
        while(!q.empty() && s[i]<q.top() && cnt[q.top()-'a'])
        {
        	//删出栈顶中的字符,并修改标记 
            vis[q.top()-'a']=0;
            q.pop();
        }
        //将选中的字符放入栈顶并标记 
        q.push(s[i]);
        vis[s[i]-'a']=1;
    }
    //将字符从栈顶拿出并逆序记录 
    string a="";
    for (int i=0;i<q.size();)
    {
        a=q.top()+a;
        q.pop();
    }
    return a;
}
全部评论

相关推荐

检票肄业生:问题很大,恰V细说
点赞 评论 收藏
分享
威猛的小饼干正在背八股:挂到根本不想整理
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务