1. 程式人生 > >32 最小子串覆蓋

32 最小子串覆蓋

ogr 數組 字符數 代碼 這樣的 ron 下一個 描述 mini

原題網址:https://www.lintcode.com/zh-cn/old/problem/minimum-window-substring/#

32. 最小子串覆蓋

討論區

給定一個字符串source和一個目標字符串target,在字符串source中找到包括所有目標字符串字母的子串。

註意事項

如果在source中沒有這樣的子串,返回"",如果有多個這樣的子串,返回起始位置最小的子串。

您在真實的面試中是否遇到過這個題? Yes 說明

在答案的子串中的字母在目標字符串中是否需要具有相同的順序?

——不需要。

樣例

給出source = "ADOBECODEBANC"

,target = "ABC" 滿足要求的解 "BANC"

挑戰

要求時間復雜度為O(n)

標簽 領英 Snapchat 優步 臉書 哈希表 思路: 參考 https://www.cnblogs.com/Allen-rg/p/5795127.html https://www.cnblogs.com/libaoquan/p/7071637.html https://blog.csdn.net/hk_john/article/details/62444016 使用哈希表,建立字符(索引)- 字符數量(值)的映射。 ASCII碼表常用字符128個,建立兩個容量為128的數組tcount[128]與scount[128],分別表示target中相應字符數量、source上的移動窗(子串)中相應字符數量,初始時兩數組相應元素都為0; 遍歷target,計算每個字符出現的次數,次數值存放在tcount【128】中; 定義int型變量begin = -1、end = source.size()、start = 0,found=0, 以及minLen = source.size(),分別代表移動窗起始位置、結束位置,窗口的移動索引,已經找到的目標串字符數量,窗口的最小長度(end-begin); 遍歷source,如果source【i】對應字符的數量加1後小於或等於該字符在target中的數量,說明找到一個字符,則found++; 若found等於target.size(),說明找到一個子串,這時就要確定移動窗的大小,即去掉前面
那些無效的字符(target中沒有但子串中有的字符),相當於確定移動窗起始位置。 方法是移動start,如果scount[source[start]] > tcount[source[start]] ,說明是無效字符(兩種情況:窗內存在該字符但目標中不存在,舍棄。另一種窗內該字符數量超過目標中數量,舍棄;),則scount[source[start]]--; start++; 重復上述過程直到scount[source[start]] = tcount[source[start]],即找到了移動窗的起始位置。 這時再判斷當前窗長度是否小於minLen,小於則更新移動窗,即 begin = start;end = i;minLen = i-start; 然後移動窗在源串上前移一位,註意舍棄起始位置字符(scount[source[start]]--; found--; start++;),繼續尋找下一個子串; 循環結束後若begin==-1說明沒找到子串,否則返回source.substr(begin,minLen+1); AC代碼:
class
Solution { public: /** * @param source : A string * @param target: A string * @return: A string denote the minimum window, return "" if there is no such a string */ string minWindow(string &source , string &target) { // write your code here if (source.empty()) { return ""; } int ssize=source.size(); int tsize=target.size(); int tcount[128]; int scount[128];//移動窗內相應字符的數量; for (int i=0;i<128;i++) { scount[i]=0; tcount[i]=0; } for (int j=0;j<tsize;j++) { tcount[target[j]]++; } int begin=-1,end=ssize,found=0,minLen=ssize;//初始化移動窗起始、終止位置、尋找過程中的子串累積長度,最小移動窗長度; for (int i=0,start=0;i<ssize;i++) { scount[source[i]]++;//遍歷源串,如果這個字符的數量加1後不超過目標串中該字符的數量,則找到了一個匹配字符,found+1; if (scount[source[i]]<=tcount[source[i]]) { found++; } if (found==tsize)//找到一個子串; { while(start<i&&scount[source[start]]>tcount[source[start]])//去掉無效字符,縮短移動窗長度; { //兩種情況:窗內存在該字符但目標中不存在,舍棄。另一種窗內該字符數量超過目標中數量,舍棄; scount[source[start]]--;//移動窗內去掉這個字符; start++;//繼續向前判斷; } //最後的結果是start對應的字符是目標中的某個字符; if (i-start<minLen) { minLen=i-start; begin=start; end=i; } //移動窗在源串上前移一位(舍棄起始字符),繼續尋找子串; scount[source[start]]--; found--; start++; } } if (begin==-1) { return ""; } else { return source.substr(begin,minLen+1); } } };

32 最小子串覆蓋