<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          542,滑動(dòng)窗口解最小覆蓋子串

          共 7399字,需瀏覽 15分鐘

           ·

          2021-04-26 07:46

          Spring is when you feel like whistling even with a shoe full of slush.

          所謂春天,就是即使鞋子灌滿泥巴,仍然想吹起口哨。

          問題描述



          給你一個(gè)字符串s、一個(gè)字符串t。返回s中涵蓋t所有字符的最小子串。如果s中不存在涵蓋t所有字符的子串,則返回空字符串""。


          注意:如果s中存在這樣的子串,我們保證它是唯一的答案。


          示例 1:

          輸入:s = "ADOBECODEBANC", t = "ABC"

          輸出:"BANC"

          示例 2:

          輸入:s = "a", t = "a"

          輸出:"a"


          提示:

          • 1 <= s.length, t.length <= 10^5

          • s 和 t 由英文字母組成


          滑動(dòng)窗口解決



          這題讓求的是s中能覆蓋t的最小子串,看到這題首先想到的就是滑動(dòng)窗口。使用兩個(gè)指針一個(gè)left,一個(gè)right,分別表示窗口的左邊界和右邊界。


          • 當(dāng)窗口內(nèi)的所有字符不能覆蓋t的時(shí)候,要擴(kuò)大窗口,也就是right往右移。

          • 當(dāng)窗口內(nèi)的所有字符可以覆蓋t的時(shí)候,記錄窗口的起始位置以及窗口的長度,然后縮小窗口(因?yàn)檫@里求的是能覆蓋的最小子串),left往右移。如果縮小的窗口還能覆蓋t,保存長度最小的窗口即可。

          • 重復(fù)上面的操作,直到窗口的右邊不能再移動(dòng)為止。


          這里我以示例1為例做個(gè)視頻,來看一下具體操作過程,加深一下理解。(如果看不清,可以切換橫向全屏觀看)

          原理搞懂了,代碼就簡單多了,但是這里有個(gè)關(guān)鍵點(diǎn),就是怎么記錄窗口內(nèi)的元素,其實(shí)很簡單,使用一個(gè)map就可以,來看下代碼。

           1public String minWindow(String s, String t) {
          2    //把t中的字符全部放到map中
          3    Map<Character, Integer> map = new HashMap<>();
          4    for (char ch : t.toCharArray())
          5        map.put(ch, map.getOrDefault(ch, 0) + 1);
          6
          7    int left = 0;//窗口的左邊界
          8    int right = 0;//窗口的右邊界
          9
          10    //滿足條件的窗口開始位置
          11    int strStart = 0;
          12    //滿足條件的窗口的長度
          13    int windowLength = Integer.MAX_VALUE;
          14
          15    while (right < s.length()) {
          16        //記錄右指針掃描過的字符
          17        char rightChar = s.charAt(right);
          18        //如果右指針掃描的字符存在于map中,就減1
          19        if (map.containsKey(rightChar))
          20            map.put(rightChar, map.getOrDefault(rightChar, 0) - 1);
          21        //記錄之后右指針要往右移
          22        right++;
          23
          24        //檢查窗口是否把t中字符全部覆蓋了,如果覆蓋了,要移動(dòng)窗口的左邊界
          25        //找到最小的能全部覆蓋的窗口
          26        while (check(map)) {
          27            //如果現(xiàn)在窗口比之前保存的還要小,就更新窗口的長度
          28            //以及窗口的起始位置
          29            if (right - left < windowLength) {
          30                windowLength = right - left;
          31                strStart = left;
          32            }
          33            //移除窗口最左邊的元素,也就是縮小窗口
          34            char leftChar = s.charAt(left);
          35            if (map.containsKey(leftChar))
          36                map.put(leftChar, map.getOrDefault(leftChar, 0) + 1);
          37            //左指針往右移
          38            left++;
          39        }
          40    }
          41    //如果找到合適的窗口就截取,否則就返回空
          42    if (windowLength != Integer.MAX_VALUE)
          43        return s.substring(strStart, strStart + windowLength);
          44    return "";
          45}
          46
          47//檢查窗口是否把字符串t中的所有字符都覆蓋了,如果map中所有
          48// value的值都不大于0,則表示全部覆蓋
          49private boolean check(Map<Character, Integer> map) {
          50    for (int value : map.values()) {
          51        //注意這里的value是可以為負(fù)數(shù)的,為負(fù)數(shù)的情況就是,相同的字符右
          52        // 指針掃描的要比t中的多,比如t是"ABC",窗口中的字符是"ABBC"
          53        if (value > 0)
          54            return false;
          55    }
          56    return true;
          57}

          上面注釋已經(jīng)寫的很詳細(xì)了,基本上也都能看懂,實(shí)際上我們還可以把HashMap換成數(shù)組,原理其實(shí)都是一樣的,來看下代碼

           1public String minWindow(String s, String t) {
          2    int[] map = new int[128];
          3    //記錄字符串t中每個(gè)字符的數(shù)量
          4    for (char ch : t.toCharArray())
          5        map[ch]++;
          6    //字符串t的數(shù)量
          7    int count = t.length();
          8    int left = 0;//窗口的左邊界
          9    int right = 0;//窗口的右邊界
          10    //覆蓋t的最小長度
          11    int windowLength = Integer.MAX_VALUE;
          12    //覆蓋字符串t開始的位置
          13    int strStart = 0;
          14    while (right < s.length()) {
          15        if (map[s.charAt(right++)]-- > 0)
          16            count--;
          17        //如果全部覆蓋
          18        while (count == 0) {
          19            //如果有更小的窗口就記錄更小的窗口
          20            if (right - left < windowLength) {
          21                windowLength = right - left;
          22                strStart = left;
          23            }
          24            if (map[s.charAt(left++)]++ == 0)
          25                count++;
          26        }
          27    }
          28    //如果找到合適的窗口就截取,否則就返回空
          29    if (windowLength != Integer.MAX_VALUE)
          30        return s.substring(strStart, strStart + windowLength);
          31    return "";
          32}


          總結(jié)



          滑動(dòng)窗口類型的題也是最常見的,一般會(huì)有兩個(gè)指針,分別指向窗口的左邊界和右邊界,如果窗口不滿足條件我們就移動(dòng)右邊界來擴(kuò)大窗口,如果滿足條件我們可以移動(dòng)左邊界來縮小窗口,確定這個(gè)更小的窗口是否還滿足條件……


          Java集合-List

          詳細(xì)介紹 IOC 和 DI

          超經(jīng)典的 25 道 MyBatis 面試題!


          以上,便是今天的分享,希望大家喜歡,覺得內(nèi)容不錯(cuò)的,歡迎「分享」「」或者點(diǎn)擊「在看」支持,謝謝各位。

          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本亲子乱婬免费播放 | 一区二区三区四区在线看 | 日日撸夜夜爱 | 麻豆成人三级片 | 亚洲成人中文网 |