AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

LeetCode 316. Remove Duplicate Letters    原题链接    困难

作者: 作者的头像   wzc1995 ,  2019-09-13 13:07:10 ,  所有人可见 ,  阅读 1546


10


2

题目描述

给定一个仅包含小写字母的字符串,去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

样例

输入:"bcabc"
输出:"abc"
输入:"cbacdcbc"
输出:"acdb"

算法

(贪心,栈) $O(n)$
  1. 使用栈来贪心的构造最终的字符串,栈的更新规则如下。
  2. 前提是当前字符没有在栈中出现。如果当前字符比栈顶字符的值小,且栈顶字符不是最后一次出现,则栈顶出栈。
  3. 重复 2 直到栈空或栈顶不满足出栈条件。此时,将当前字符压入栈中,且标记当前字符出现过。
  4. 最后将栈中元素从栈底到栈顶的顺序输出。

时间复杂度

  • 预处理字符最后出现的位置为 $O(n)$。
  • 每个元素最多进栈一次,出栈一次,故总时间复杂度为 $O(n)$。

空间复杂度

  • 使用了栈来存储当前答案,但栈的大小最长不超过 26。
  • 其他辅助和标记数组的长度都是 26,最后答案的长度也不超过 26。
  • 所以可以认为空间复杂度为 $O(1)$。

C++ 代码

class Solution {
public:
    string removeDuplicateLetters(string s) {
        vector<int> last(26, -1);
        vector<char> st;
        vector<bool> vis(26, false);
        int n = s.length();

        for (int i = 0; i < n; i++)
            last[s[i] - 'a'] = i;

        for (int i = 0; i < n; i++) {
            if (vis[s[i] - 'a'])
                continue;
            while (!st.empty() && st.back() > s[i]) {
                if (last[st.back() - 'a'] < i)
                    break;
                vis[st.back() - 'a'] = false;
                st.pop_back();
            }
            st.push_back(s[i]);
            vis[s[i] - 'a'] = true;
        }

        string ans;
        for (char c : st)
            ans += c;
        return ans;
    }
};

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息