LeetCode(76): 最小覆蓋子串


Hard!

題目描述:

給定一個字符串 S 和一個字符串 T,請在 S 中找出包含 T 所有字母的最小子串。

示例:

輸入: S = "ADOBECODEBANC", T = "ABC"
輸出: "BANC"

說明:

  • 如果 S 中不存這樣的子串,則返回空字符串 ""
  • 如果 S 中存在這樣的子串,我們保證它是唯一的答案。

解題思路:

這道題的要求是要在O(n)的時間度里實現找到這個最小窗口字串,那么暴力搜索Brute Force肯定是不能用的,我們可以考慮哈希表,其中key是T中的字符,value是該字符出現的次數

- 我們最開始先掃描一遍T,把對應的字符及其出現的次數存到哈希表中。

- 然后開始遍歷S,遇到T中的字符,就把對應的哈希表中的value減一,直到包含了T中的所有的字符,紀錄一個字串並更新最小字串值。

- 將子窗口的左邊界向右移,略掉不在T中的字符,如果某個在T中的字符出現的次數大於哈希表中的value,則也可以跳過該字符。

C++解法一:

 1 class Solution {
 2 public:
 3     string minWindow(string S, string T) {
 4         if (T.size() > S.size()) return "";
 5         string res = "";
 6         int left = 0, count = 0, minLen = S.size() + 1;
 7         unordered_map<char, int> m;
 8         for (int i = 0; i < T.size(); ++i) {
 9             if (m.find(T[i]) != m.end()) ++m[T[i]];
10             else m[T[i]] = 1;
11         }
12         for (int right = 0; right < S.size(); ++right) {
13             if (m.find(S[right]) != m.end()) {
14                 --m[S[right]];
15                 if (m[S[right]] >= 0) ++count;
16                 while (count == T.size()) {
17                     if (right - left + 1 < minLen) {
18                         minLen = right - left + 1;
19                         res = S.substr(left, minLen);
20                     }
21                     if (m.find(S[left]) != m.end()) {
22                         ++m[S[left]];
23                         if (m[S[left]] > 0) --count;
24                     }
25                     ++left;
26                 }
27             }
28         }
29         return res;
30     }
31 };

這道題也可以不用哈希表,直接用個int的數組來代替,因為ASCII只有256個字符,所以用兩個大小為256的int數組即可代替哈希表,其余部分的思路完全相同。

C++解法二:

 1 class Solution {
 2 public:
 3     string minWindow(string S, string T) {
 4         if (T.size() > S.size()) return "";
 5         string res = "";
 6         int left = 0, count = 0, minLen = S.size() + 1;
 7         int tm[256] = {0}, sm[256] = {0};
 8         for (int i = 0; i < T.size(); ++i) ++tm[T[i]];
 9         for (int right = 0; right < S.size(); ++right) {
10             if (tm[S[right]] != 0) {
11                 ++sm[S[right]];
12                 if (sm[S[right]] <= tm[S[right]]) ++count;
13                 while (count == T.size()) {
14                     if (right - left + 1 < minLen) {
15                         minLen = right - left + 1;
16                         res = S.substr(left, minLen);
17                     }
18                     if (tm[S[left]] != 0) {
19                         --sm[S[left]];
20                         if (sm[S[left]] < tm[S[left]]) --count;
21                     }
22                     ++left;
23                 }
24             }
25         }
26         return res;
27     }
28 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM