雙指針之滑動(dòng)窗口僧家,Java

Leetcode 209題: 長(zhǎng)度最小的子數(shù)組

給定一個(gè)含有 n 個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù) s 拌倍,找出該數(shù)組中滿足其和 ≥ s 的長(zhǎng)度最小的連續(xù)子數(shù)組箱季,并返回其長(zhǎng)度涯穷。如果不存在符合條件的連續(xù)子數(shù)組,返回 0藏雏。

來(lái)源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有拷况。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系官方授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

這種連續(xù)子數(shù)組的問(wèn)題赚瘦,暴力解法粟誓,也就是列出所有的子數(shù)組來(lái)進(jìn)行求和,再一一比對(duì)起意,符合要求的存儲(chǔ)子數(shù)組的長(zhǎng)度鹰服,最后輸出最小的長(zhǎng)度,這會(huì)導(dǎo)致O(n^3)的復(fù)雜度揽咕。

 public int minSubArrayLen(int s, int[] nums) {
        int len = nums.length;
        int res = len + 1;
        for(int l = 0; l < len; l ++){
            for(int r = l; r < len; r ++){
                int sum = 0;
                for(int i = l; i <= r; i ++){
                    //如果要查看子數(shù)組的序列获诈,可打印i
                    //System.out.print(i+"-");
                    sum += nums[i];
                    if(sum >= s)
                        res = Math.min(res, r - l + 1);
                }
                //System.out.printl();
            }
        }
        
        if(res == len + 1)
            return 0;
        return res;
    }

使用滑動(dòng)窗口,可以將復(fù)雜度下降至O(n)心褐,其中兩個(gè)指針l與r切诀,分別指向窗口的左右邊界微王,當(dāng)窗口內(nèi)數(shù)值的和大于s時(shí),左邊界往前移,去除最左邊的數(shù)值淮摔,如果小于s時(shí),則右邊界往前配深,新增加一個(gè)數(shù)值鹏漆。

public int minSubArrayLen(int s, int[] nums) {
        int len = nums.length;

        int l = 0, r = -1;
        int sum = 0;
        int res = len + 1;
        while (l < len){

            if(r + 1 < len && sum < s)
                sum  += nums[++r];
            else
                sum -= nums[l++];

            if(sum >= s)
                res = Math.min(res, r-l+1);
        }

        if(res == len + 1)
            return  0;

        return res;
    }

Leetcode 3題: 無(wú)重復(fù)字符的最長(zhǎng)字串

這里使用了一個(gè)小技巧:每一次一個(gè)新的字符再加入子串時(shí),都需要判斷一下這個(gè)字符是否已經(jīng)出現(xiàn)過(guò)袍睡,可以使用一個(gè)新的數(shù)字知染,它的索引對(duì)應(yīng)字符的ASCII碼,這里也可以同時(shí)處理大小寫不敏感的問(wèn)題斑胜。
當(dāng)這個(gè)索引對(duì)應(yīng)的值為0時(shí)控淡,就說(shuō)明未出現(xiàn)過(guò),為1時(shí)止潘,就說(shuō)明出現(xiàn)過(guò)1次掺炭。
引申一下,就可以解決字符串允許重復(fù)k次的子串長(zhǎng)度凭戴。

public int lengthOfLongestSubstring(String s) {
        int[] freq = new int[256];  //記錄字符出現(xiàn)的次數(shù)

        int l = 0, r = -1;  //滑動(dòng)窗口為s[l...r]
        int res = 0;

        while( l < s.length() ){
            if( r + 1 < s.length() && freq[s.charAt(r+1)] == 0)
                freq[s.charAt(++r)] ++;
            else
                freq[s.charAt(l++)] --;

            res = Math.max(res, r-l+1);
        }
        return res;
    }

Leetcode 438題:找到字符串中的anagram

List<Integer> res = new ArrayList();
        if(s.length() < p.length())
            return res;
        assert p.length() > 0;
        
        char[] arrS = s.toCharArray();
        char[] arrP = p.toCharArray();

        // 定義一個(gè) needs 數(shù)組來(lái)看 arrP 中包含元素的個(gè)數(shù)
        int[] freq_p = new int[26];
        // 定義一個(gè) window 數(shù)組來(lái)看滑動(dòng)窗口中是否有 arrP 中的元素涧狮,并記錄出現(xiàn)的個(gè)數(shù)
        int[] freq_s = new int[26];

        // 先將 arrP 中的元素保存到 needs 數(shù)組中
        for (int i = 0; i < arrP.length; i++) {
            freq_p[arrP[i] - 'a'] ++;
        }
        // 在s[l...r]中的元素與p進(jìn)行比對(duì),一開(kāi)始這個(gè)區(qū)間里沒(méi)有元素么夫,所以r為-1
        int l = 0;
        int r = -1;
        //Sliding window: s[l...r] r - l + 1<= p.length()
        //if freq_s[r] < freq_p[r] r++
        //if freq_s[r] > freq_p[r]  freq_s[l]-- && l++者冤,也就是整個(gè)窗口左移
        //if freq_s[r] == freq_[r]
            //if r - l + 1 == p.length()
                //res.add(l) && l++ && freq_s[l]--
        // 右窗口開(kāi)始不斷向右移動(dòng)
        while ( r + 1 < arrS.length ) {
            
            if( r - l + 1 < arrP.length )
                freq_s[arrS[++r] - 'a'] ++;

            while( freq_s[arrS[r] - 'a'] > freq_p[arrS[r] - 'a'] && l  < arrS.length)
                freq_s[arrS[l++] - 'a'] --;

            if( r - l + 1 >= arrP.length ){
                res.add(l);
                freq_s[arrS[l++] - 'a'] --;
            }
        }
        return res;

Leetcode 76:最小覆蓋子串

 public String minWindow(String s, String t) {
       if (s.length() < t.length())
            return "";
        assert t.length() > 0;

        char[] arrS = s.toCharArray();
        char[] arrT = t.toCharArray();


        int[] freq = new int[128];
        int[] window = new int[128];
        int count = 0;

        for (char c : arrT) {
            freq[c]++;
        }


        int minLen = s.length() + 1;
        int startIndex = -1;

        // 在s[l...r)中的元素與p進(jìn)行比對(duì),一開(kāi)始這個(gè)區(qū)間里沒(méi)有元素档痪,所以r為0
        int l = 0, r = 0;
        while (r < arrS.length) {

            if(freq[arrS[r]] == 0){
                r++;
                continue;
            }

            if ( window[arrS[r]] < freq[arrS[r]])
                count++;

            window[arrS[r++]]++;

            while (count == arrT.length) {
                if(r - l < minLen){
                    minLen = r - l;
                    startIndex = l;
                }
                if ( window[arrS[l]] == 0){
                    l++;
                    continue;
                }
                //給startIndex賦值
                //移動(dòng)左邊界,判斷count是否--
                //當(dāng)count不滿足條件涉枫,繼續(xù)移動(dòng)右邊界
                if(window[arrS[l]] == freq[arrS[l]]){
                    count--;
                }
                window[arrS[l++]]--;
            }
        }
        if (minLen == s.length() + 1)
            return "";

        return s.substring(startIndex, startIndex + minLen);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市钞它,隨后出現(xiàn)的幾起案子拜银,更是在濱河造成了極大的恐慌殊鞭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尼桶,死亡現(xiàn)場(chǎng)離奇詭異操灿,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泵督,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門趾盐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人小腊,你說(shuō)我怎么就攤上這事救鲤。” “怎么了秩冈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵本缠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我入问,道長(zhǎng)丹锹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任芬失,我火速辦了婚禮楣黍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棱烂。我一直安慰自己租漂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布颊糜。 她就那樣靜靜地躺著哩治,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芭析。 梳的紋絲不亂的頭發(fā)上锚扎,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天吞瞪,我揣著相機(jī)與錄音馁启,去河邊找鬼。 笑死芍秆,一個(gè)胖子當(dāng)著我的面吹牛惯疙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妖啥,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼霉颠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了荆虱?” 一聲冷哼從身側(cè)響起蒿偎,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤朽们,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后诉位,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體骑脱,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年苍糠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了叁丧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岳瞭,死狀恐怖拥娄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瞳筏,我是刑警寧澤稚瘾,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站姚炕,受9級(jí)特大地震影響孟抗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钻心,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一凄硼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捷沸,春花似錦摊沉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苍柏,卻和暖如春尼斧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背试吁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工棺棵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熄捍。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓烛恤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親余耽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缚柏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348