标签: 单调栈
题目
\1081. Smallest Subsequence of Distinct Characters
Medium
Return the lexicographically smallest subsequence of text
that contains all the distinct characters of text
exactly once.
Example 1:
Input: "cdadabcc"
Output: "adbc"
Example 2:
Input: "abcd"
Output: "abcd"
Example 3:
Input: "ecbacba"
Output: "eacb"
Example 4:
Input: "leetcode"
Output: "letcod"
Note:
1 <= text.length <= 1000
text
consists of lowercase English letters.
greedy wrong answer
DP TLE思路
用map记录所有当前可能存在的状态, 和之前的 1049 last stone weight 2不同,数字的加 加减减可以出想相同的数,进行减枝,字符串无法减枝
单调栈思路
-
找到当前位置的单调栈序列(这种纯单调栈的思路很容易)
-
所有出现的字符都要出现,有的违背单调原则的字符,通过cnt数组,判断后面是否还会出现,如果不出现,就只能放在违背单调的位置上
-
每个字符已经出现了,如果当前字符已经在单调栈的前面了, 那就不用在考虑把他放到单调栈中了,因为单调栈的性质已经保证他在最小的位置上了。使用used判断之前是否已经存在
小结
单调栈:最小序列
cnt:以后该字符是否出现
used:该字符是否 已经在单调栈中
DP TLE CODE
class Solution {
public:
bool static cmp(string a, string b){
int m = a.length();
for(int i=0; i<m; i++){
if(a[i] < b[i]){
continue;
}else{
return false;
}
}
return true;
}
string smallestSubsequence(string text) {
set<string> strs_a;
set<string> strs_b;
string tmp;
tmp = text[0];
strs_a.insert(tmp);
for(int i=0; i<text.length(); i++){
strs_b = strs_a;
strs_a.clear();
for(auto str : strs_b){
tmp = text[i];
auto itr = find(begin(str), end(str), text[i]);
if (itr == end(str)){
str+=tmp;
strs_a.insert(str);
}else {
strs_a.insert(str);
str.erase(itr);
str+=tmp;
strs_a.insert(str);
}
}
}
string ans(text.length(), 'z');
for(auto str : strs_a){
cout <<str<<endl;
ans = min(ans, str, cmp);
}
return ans;
}
};
单调栈
//
// Created by hanshan on 19-6-11.
//
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
string smallestSubsequence(string text) {
string res = "";
vector<int> cnt(26);
vector<int> used(26);
for(auto ch : text){
cnt[ch-'a'] ++;
}
for(auto ch : text){
cnt[ch-'a'] --;
if(used[ch-'a']) continue;
while( !res.empty() && ch < res.back() && cnt[res.back()-'a']){
used[res.back()-'a'] = 0;
res.pop_back();
}
res.push_back(ch-'a');
}
return res;
}
};