1. 程式人生 > >【LeetCode】76. 最小覆蓋子串 結題報告 (C++)

【LeetCode】76. 最小覆蓋子串 結題報告 (C++)

題目描述:

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

示例:

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

說明:

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

解題方案:

該題給出的提示是雙指標、雜湊表,怎麼感覺這題有點動態規劃的意思。後來在網上看一些大神的程式碼,思路大致都是一樣的,參考地址https://blog.csdn.net/qq_38595487/article/details/80388100 這篇部落格採用的語言是Java,後來我改成了C++,其中有些函式存在的差別,需要注意一下。

class Solution {
public:
    string minWindow(string s, string t) {
        
        //hashmap來統計t字串中各個字母需要出現的次數
        map<char, int> HashMap;
        for (int i = 0; i < t.size(); i ++)
            HashMap[t[i]] = HashMap.find(t[i]) != HashMap.end()? HashMap[t[i]] + 1 : 1;
 
        //用來計數 判斷當前子字串中是否包含了t中全部字元
        int count = 0;
        //記錄當前子字串的左右下標值
        int left = 0;
        int right = 0;
        //記錄當前最小子字串的大小以及第一最後字元的下標值
        int min = INT_MAX;
        int minLeft = 0;
        int minRight = 0;
 
        for (; right < s.length() ; right ++) {
            if (HashMap.find(s[right]) != HashMap.end()){//向後遍歷出所包含t的字串
                if(HashMap[s[right]] > 0)   count ++;
                HashMap[s[right]] =  HashMap[s[right]] - 1;
            }
            while (count == t.length()){//得出一個符合條件的子字串
                if (right - left < min){//更新min minLeft minRight 資訊
                    min = right - left;
                    minLeft = left;
                    minRight = right;
                }
                
                if (HashMap.find(s[left]) != HashMap.end()){//向左收縮 判斷所刪減的字元是否在map中
                    if (HashMap[s[left]] >= 0)  count --;//count--時需要判斷一下是否需要-- 
                    HashMap[s[left]] =  HashMap[s[left]] + 1;
                }
                left ++;
            }
        }
        return min == INT_MAX ?  "" : s.substr(minLeft, min+1);

    }
};