Remove Duplicate Letters 刪除重複元素
一、概述
輸入一個字串,刪除其中重複的字元,並保證剩餘的元素排列是所有可能性中最小的。
這什麼意思?
以cbacdcbc為例,刪完重複的,剩下abcd四個字元,那麼我可以這樣刪:
c b a c d c b c
c b a x d x x x
結果就是cbad
也可以這樣刪
x x a c d x b x
結果就是acdb,這個字典序比cbad小,要這個。
二、分析
麻煩。很複雜。我自己分析的貪心演算法都只能找到區域性最優,找不到全域性最優。
先想一個問題,我們只遍歷一遍的話,如何判斷當前的字元放不放到結果中?
以字串cbacdcbc為例
首先是c,放入結果,結果為c
然後是b,放入結果,結果為cb
然後是a,放入結果,結果為cba
然後是c,結果中已經有c了,那這兩個c要哪個呢?要前面那個是cba,後邊這個是bac,那肯定要後邊這個不要前邊這個
那我這麼看太麻煩了不說,還有這種情況:
對於字串bcabc
首先是bca,結果是bca,
然後是b,結果中已經有b了,那要之前的b還是這個b?要之前的b,結果是bca,這個b,結果是cab,要之前的。
然後是c,結果中已經有c了,那要之前的c還是這個c?要之前的c,結果是bca,這個c,結果是bac,要這個。
所以結果是bac。結果錯了。
應該是abc。為什麼?因為我們應該要第二個b而不是第一個。
也就是說,不能只遍歷一次,只遍歷一次只能得到區域性最優,無法得到全域性最優。
正確演算法是遍歷兩次。第一次知道各個字元的儲量。仍然以cbacdcbc為例。
先遍歷一次探明儲量。a有一個,b有2,c有4,d有1。
然後遍歷第二次:
首先是c,放入結果,結果為c
然後是b,先看結果,結果中有c,現在有b,是委屈一下b,把b放在c後面,結果是bc,還是不要這個c了,結果仍然是b?
也就是說,這個c到底要不要?那得看後面有沒有c,後面還有c,那麼必定最後有結果…b…c;後面沒有c,那麼這個獨苗就得保住。之前已經探明瞭儲量,有c,那麼這個c就滾蛋,目前結果是b。
總結起來就是:保這個c,結果是cb…,不保,結果是b…c…。我們要字典序最小,那麼肯定要後者。
之後是a。同理,由於b比a大,是委屈這個a,結果是ba,還是不要這個b,結果是a。看b的儲量。b有倆,那不客氣了,b滾蛋
結果為a
之後是c,尾巴是a,比c小,放入結果,結果是ac。
之後是d,尾巴是c,放入結果,結果是acd。
之後是c,結果中已經有c了,那麼這個c就不用看了。因為結果中一定是當前最優的。
之後是b,尾巴是d,比b大,想刪,只有一個,刪不了,那b就只能放在最後,結果是acdb。
以此類推。
總結一下:先探明各個字元的儲量。然後遍歷一次想得到結果。就得拿捏好到底要哪個字元。我們要求字元序越小越好,也就是說小的字元越在前越好。
那麼,每當遇到一個結果中沒有的字元,就從最後一個當前的結果開始比,最後一個字元比當前字元大,儲量還有,那麼就把它刪了,否則就把當前字元放在最後。
核心就是b…c…一定比cb好。那麼我就把cb這個c撇了,反正之後還有。優化結果更重要。
先保證有無,再保證字典序最小。
三、總結
有點暈,這個演算法不太好想,得明確貪心的規則:
當前字元在結果中已存在?
是,跳過;否,結尾字元儲量還有?
否,當前字元放在最後;是,當前字元比最後一個字元小?
否,當前字元放到最後;是,刪除最後一個,繼續和最後一個比較。
PS:程式碼如下:
class Solution {
public:
string removeDuplicateLetters(string s) {
string res="";
vector<int> HT(256,0);
for(auto i:s)
HT[i]++;
for(auto i:s)
{
HT[i]--;
if(res=="")
{
res+=i;
continue;
}
else if(res.find(i)!=string::npos)
continue;
else
{
while(res!=""&&HT[res[res.size()-1]]>0&&res[res.size()-1]>i)
res.pop_back();
if(res.find(i)==string::npos)
res+=i;
}
}
return res;
}
};
相關文章
- LeetCode-Remove Duplicate LettersLeetCodeREM
- [LintCode/LeetCode] Remove Duplicate LettersLeetCodeREM
- JavaScript 刪除陣列重複元素JavaScript陣列
- JavaScript陣列刪除重複元素JavaScript陣列
- 如何刪除ArrayList中的重複元素
- 【leetcode】26. Remove Duplicates from Sorted Array 刪除有序陣列的重複元素LeetCodeREM陣列
- js刪除陣列中重複的元素JS陣列
- js刪除陣列中的重複元素JS陣列
- javascript刪除陣列重複元素程式碼JavaScript陣列
- ES6刪除字串中重複的元素字串
- JavaScript 拼接多個陣列並刪除重複元素JavaScript陣列
- javascript刪除陣列重複元素程式碼例項JavaScript陣列
- 演算法提高 11-2刪除重複元素演算法
- js刪除陣列重複元素程式碼例項JS陣列
- javascript刪除陣列中的重複元素程式碼JavaScript陣列
- javascript刪除陣列中重複元素程式碼例項JavaScript陣列
- Java刪除ArrayList中的重複元素的2種方法Java
- 刪除重複資料
- 刪除oracle重複值Oracle
- JavaScript 刪除重複字元JavaScript字元
- mysql 刪除重複項MySql
- LeetCode C++ 316. Remove Duplicate Letters【Stack/Greedy/String】中等LeetCodeC++REM
- js連線多個陣列並刪除重複的元素JS陣列
- 演算法刪除單連結串列中重複的元素演算法
- 三種方法刪除列表中重複的元素及效率分析!
- JavaScript 刪除字串重複字元JavaScript字串字元
- mongodb刪除重複資料MongoDB
- MySQL刪除重複資料MySql
- 刪除Oracle重複記錄Oracle
- oracle刪除重複記錄Oracle
- O(1) 時間插入、刪除和獲取隨機元素,允許元素重複隨機
- 83. 刪除排序連結串列中的重複元素(JavaScript版)排序JavaScript
- js利用正規表示式刪除陣列中的重複元素JS陣列
- JavaScript刪除陣列重複元素的5個高效演算法JavaScript陣列演算法
- 力扣-83. 刪除排序連結串列中的重複元素力扣排序
- JavaScript刪除字串中重複字元JavaScript字串字元
- 刪除表裡重複資料
- oracle刪除多餘重複行Oracle