题目要求:
- 要去重(应用
freq[256] = {false}
数组来去重)
2.去除字符串中的字符顺序不能打乱s
中字符出现的相对顺序(通过栈来保存字符相对顺序,从而保存结果串,先进后出的特点使我们可以立即操作插入的字符)
3.在所有符合上一条的去重字符串中,字典序最小的作为最终结果(类似单调栈的思路,配合计数器Count不断pop掉不符合的字符,保证最后得到的结果字典序最小)
class Solution {
public:
string removeDuplicateLetters(string s) {
stack<char> stk;
int Count[256] = {0}; //记录字符串中,每个字符的数量
for(int i =0; i < s.size(); i++)
Count[s[i]]++;
bool freq[256] = {false};
for(char c : s){
Count[c]--; //每遍历一个字符,则将此字符数量减一
if(freq[c])
continue;
while(!stk.empty() && stk.top() > c){
if(Count[stk.top()] == 0) //若后面不存在此元素,则停止pop
break;
freq[stk.top()] = false;
stk.pop();
}
stk.push(c);
freq[c] = true;
}
string res;
while(!stk.empty()){
res += stk.top();
stk.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
贪心策略:按照右边界排序,从左向右记录非交叉区间的个数。最后用总区间数减去非交叉区间数就是需要移除的区间个数。
右边界排序之后,局部最优:优先选右边界小的区间,所以从左向右遍历,留给下一个区间的空间大一些,从而尽量避免交叉。全局最优:选取最多的非交叉区间。
class Solution {
public:
static bool cmp(const vector<int> &a, const vector<int> &b){
return a[1] < b[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if(intervals.size() == 0) return 0;
sort(intervals.begin(), intervals.end(), cmp); //快排
int Count = 1; //记录非交叉区间的个数
int end = intervals[0][1]; //记录区间分割点
for(int i = 1; i < intervals.size(); i++){
if(end <= intervals[i][0]){
end = intervals[i][1];
Count++;
}
}
return intervals.size() - Count;
}
};