[Leetcode] 316. Remove Duplicate Letters 解题报告

来源:互联网 发布:淘宝饰品店铺名 编辑:程序博客网 时间:2024/06/03 05:29

题目

Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.

Example:

Given "bcabc"
Return "abc"

Given "cbacdcbc"
Return "acdb"

思路

这道题目的最优解还不是那么容易想到,解释起来还比较费劲。我下面结合具体例子来说明一下吧。

首先我们统计每个字符出现的次数,这样在顺序扫描字符串的时候,就可以知道后面还会不会再出现这个字符。在顺序扫描的时候,如果发现当前字符比结果中的最后一个字符小,并且结果中的最后一个字符在后面还会出现,那么就把结果中的最后一个字符弹出,这是因为弹出后形成的字符串的字典序必然比不弹出的小。以字符串bcabc为例:

1)b:由于此时结果集为空,所以加入结果集,使得ret == “b”;

2)c:由于c > ret.back() == b,所以c直接加入结果集,此时ret == “bc”;

3)a:由于a < c,并且c在之后还会出现,所以不用此时的c,把c从结果集中弹出,此时ret == “b”;此时仍然有a < b,并且b在之后还会出现,所以不用此时的b,把b从结果集中弹出,此时ret == ""。最后再加入a,使得ret == “a”;

4)b:此时b > a,所以在结果集中加入b,使得 ret == "ab";

5)c:此时c > b,所以在结果集中加入c,使得 ret == “abc”。这就是最终结果。

算法的空间复杂度是输出敏感性的,最高可以达到O(n),时间复杂度是O(n),因为每个字符最多被入栈和出栈各一次。

代码

class Solution {public:    string removeDuplicateLetters(string s) {        string ret;        vector<int> hash(26, 0);        vector<bool> visited(26, false);        for(auto ch : s) {            ++hash[ch - 'a'];        }        for(auto ch : s) {            --hash[ch - 'a'];            if(visited[ch - 'a']) {                continue;            }            while(ret.size() > 0 && ch < ret.back() && hash[ret.back() - 'a'] > 0) {                visited[ret.back() - 'a'] = false;                ret.pop_back();            }            ret += ch;            visited[ch - 'a'] = true;        }        return ret;    }};

原创粉丝点击