一. 题目描述
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"
,如果不考虑字典序,则结果可以是"bca"
、"cab"
、"abc"
、"bac"
,单字典序最小只有:"abc"
。
这里的方法定义了两个容器,分别用于记录每个小写字符出现的次数:count[26]
,以及每个字符是否已使用:visit[26]
。
这里采取的方法是两次遍历字符串,第一次遍历时,记录每个字符出现的次数。
第二遍遍历时,先判断某下标的字符s[j]
,如果它已经存在于结果result
中,visit[s[j] - 'a']
为true
,直接跳过该下标;否则,对比s[j]
与字符串结果result
的尾部字符大小,当且仅当result
末尾元素大于s[j]
,且result
末尾元素剩下的个数还不为0
,此时,用s[j]
替换result
末尾元素,并将末尾元素的visit
值重置为false
,即未使用。
三. 示例代码
class Solution {
public:
string removeDuplicateLetters(string s) {
int n = s.length();
if (n < 2) return s;
string result = "";
vector<int> count(26, 0);
vector<bool> visit(26, false);
for (int i = 0; i < n; ++i) ++count[s[i] - 'a'];
for (int j = 0; j < n; ++j)
{
--count[s[j] - 'a'];
if (visit[s[j] - 'a']) continue;
while (!result.empty() && result.back() > s[j] && count[result.back() - 'a'] > 0)
{
visit[result.back() - 'a'] = false;
result.pop_back();
}
result += s[j];
visit[s[j] - 'a'] = true;
}
return result;
}
};
四. 小结
该题为字符串操作,比较复杂。