国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一)

這篇具有很好參考價(jià)值的文章主要介紹了【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

??樊梓慕:個(gè)人主頁(yè)

???個(gè)人專欄:《C語(yǔ)言》《數(shù)據(jù)結(jié)構(gòu)》《藍(lán)橋杯試題》《LeetCode刷題筆記》《實(shí)訓(xùn)項(xiàng)目》《C++》《Linux》《算法》

??每一個(gè)不曾起舞的日子,都是對(duì)生命的辜負(fù)


目錄

前言

1.長(zhǎng)度最小的子數(shù)組

滑動(dòng)窗口類問題解題思路大綱:

2.無重復(fù)字符的最長(zhǎng)字串

3.最大連續(xù)1的個(gè)數(shù)Ⅲ

4.將 x 減到 0 的最小操作數(shù)(medium)


前言

本篇文章主要會(huì)講解滑動(dòng)窗口的解題思想,滑動(dòng)窗口實(shí)際上就是利用雙指針的基礎(chǔ)思想,并且利用單調(diào)性進(jìn)行解題的方法。

滑動(dòng)窗口所用到的雙指針是用來維護(hù)這個(gè)所謂的『 窗口』,所以這兩個(gè)指針是『 同向』且『 不回退』的,這也就決定了滑動(dòng)窗口解題的時(shí)間復(fù)雜度最多為O(2N) 即O(N),所以滑動(dòng)窗口是一種非常優(yōu)秀的算法思想。

那么滑動(dòng)窗口思想具體的應(yīng)用,以及如何分析判斷是否適用滑動(dòng)窗口解題呢?


歡迎大家??收藏??以便未來做題時(shí)可以快速找到思路,巧妙的方法可以事半功倍。

=========================================================================文章來源地址http://www.zghlxwxcb.cn/news/detail-825716.html

GITEE相關(guān)代碼:??樊飛 (fanfei_c) - Gitee.com??

=========================================================================


1.長(zhǎng)度最小的子數(shù)組

209. 長(zhǎng)度最小的子數(shù)組 - 力扣(LeetCode)https://leetcode.cn/problems/minimum-size-subarray-sum/

給定一個(gè)含有?n?個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù)?target?。

找出該數(shù)組中滿足其總和大于等于?target?的長(zhǎng)度最小的?連續(xù)子數(shù)組?[numsl, numsl+1, ..., numsr-1, numsr]?,并返回其長(zhǎng)度。如果不存在符合條件的子數(shù)組,返回?0?。

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

如果依照暴力枚舉的策略,解題思路大致如下:

利用雙指針,一個(gè)指針固定,移動(dòng)另一個(gè)指針,當(dāng)兩個(gè)指針中間的所有元素和大于等于目標(biāo)值target時(shí),記錄此時(shí)的長(zhǎng)度,然后循環(huán)往復(fù),求長(zhǎng)度最小值。

代碼如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        // 記錄結(jié)果
        int ret = INT_MAX;
        int n = nums.size();
        // 枚舉出所有滿?和?于等于 target 的?數(shù)組[start, end]
        // 由于是取到最?,因此枚舉的過程中要盡量讓數(shù)組的?度最?
        // 枚舉開始位置
        for (int start = 0; start < n; start++)
        {
            int sum = 0; // 記錄從這個(gè)位置開始的連續(xù)數(shù)組的和
            // 尋找結(jié)束位置
            for (int end = start; end < n; end++)
            {
                sum += nums[end]; // 將當(dāng)前位置加上
                if (sum >= target) // 當(dāng)這段區(qū)間內(nèi)的和滿?條件時(shí)
                {
                    // 更新結(jié)果,start 開頭的最短區(qū)間已經(jīng)找到
                    ret = min(ret, end - start + 1);
                    break;
                }
            }
        }
        // 返回最后結(jié)果
        return ret == INT_MAX ? 0 : ret;
    }
};

可其實(shí)這其中有太多可以忽略掉的枚舉區(qū)間,我們來分析一下:

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

本題要求的是長(zhǎng)度最小子數(shù)組,所以此時(shí)一定是要更新left的位置即可,這就達(dá)到了不回退的目的。

注意:要在移動(dòng)left之前更新結(jié)果。

所以此類問題,我們可以將left和right中間的區(qū)域看作一塊窗口,該窗口不斷的向后移動(dòng),直到right超出數(shù)組為止。

在這一過程中:

  • right移動(dòng)導(dǎo)致元素進(jìn)入窗口的行為我們稱為『 進(jìn)入窗口』;
  • left移動(dòng)導(dǎo)致元素離開窗口的行為我們稱為『 離開窗口』;
  • 判斷l(xiāng)eft和right維護(hù)的窗口是否滿足題目條件我們稱為『 判斷』;
  • 滿足題目條件時(shí)更新結(jié)果的行為我們稱為『 更新結(jié)果』。

所以以上這些步驟就構(gòu)成了『 滑動(dòng)窗口』類問題的解題思路。

滑動(dòng)窗口類問題解題思路大綱:

①left=0,right=0;

②進(jìn)入窗口;

③判斷;????????

????????離開窗口;

④更新結(jié)果;

其中更新結(jié)果取決于具體的題目要求,『 就題論題』。

比如本題就需要在『 離開窗口』之前『 更新結(jié)果』。

有了思路,畫圖獨(dú)立完成代碼,不要直接看博主的代碼。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left=0,right=0;
        int size=nums.size();
        int sum=0;
        int len=INT_MAX;
        while(right<size)
        {
            sum+=nums[right];//進(jìn)入窗口
            while(sum>=target)//判斷
            {
                len=min(len,right-left+1);//更新結(jié)果
                sum-=nums[left++];//離開窗口
            }
            right++;
        }
        return len == INT_MAX ? 0 : len;
    }
};

2.無重復(fù)字符的最長(zhǎng)字串

3. 無重復(fù)字符的最長(zhǎng)子串 - 力扣(LeetCode)https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/

給定一個(gè)字符串?s?,請(qǐng)你找出其中不含有重復(fù)字符的?最長(zhǎng)子串?的長(zhǎng)度。

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

其實(shí)滑動(dòng)窗口類題目最重要的是弄清楚『 為什么』要使用滑動(dòng)窗口,而不是『 怎樣』適用滑動(dòng)窗口。

像本題,你是如何分析出要使用滑動(dòng)窗口的呢?

首先依據(jù)暴力枚舉的策略,同樣固定一個(gè)指針,移動(dòng)另一指針,搭配哈希表得到最長(zhǎng)字串:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int ret = 0; // 記錄結(jié)果
        int n = s.length();
        // 1. 枚舉從不同位置開始的最?重復(fù)?串
        // 枚舉起始位置
        for (int i = 0; i < n; i++)
        {
            // 創(chuàng)建?個(gè)哈希表,統(tǒng)計(jì)頻次
            int hash[128] = { 0 };
            // 尋找結(jié)束為?
            for (int j = i; j < n; j++)
            {
                hash[s[j]]++; // 統(tǒng)計(jì)字符出現(xiàn)的頻次
                if (hash[s[j]] > 1) // 如果出現(xiàn)重復(fù)的
                    break;
                // 如果沒有重復(fù),就更新 ret
                ret = max(ret, j - i + 1);
            }
        }
        // 2. 返回結(jié)果
        return ret;
    }
};

注意:因?yàn)轭}目說明都為字符,所以我們可以創(chuàng)建一個(gè)128大小的數(shù)組用來模擬哈希表,沒有必要真的申請(qǐng)一個(gè)哈希表出來。?

然后才能依據(jù)這一暴力枚舉的底子我們做優(yōu)化。

思路:

當(dāng)right指向重復(fù)字符時(shí),我們是否需要直接讓right回退,left++呢?

其實(shí)如果right指向重復(fù)字符了,那么就證明此時(shí)就是left開頭代表的窗口的最長(zhǎng)字串了(因?yàn)樵谶@之前right沒有指向重復(fù)字符),所以此時(shí)不需要移動(dòng)right,而應(yīng)該移動(dòng)left直到?jīng)]有重復(fù)字符為止,然后再移動(dòng)right即可。

  • 如果這個(gè)字符出現(xiàn)的頻次超過1 ,說明窗口內(nèi)有重復(fù)元素,那么就從左側(cè)開始劃出窗口,直到這個(gè)元素的頻次變?yōu)?,然后再更新結(jié)果。
  • 如果沒有超過1 ,說明當(dāng)前窗口沒有重復(fù)元素,可以直接更新結(jié)果。

所以『 更新結(jié)果』我們可以統(tǒng)一放在『 判斷』的外面。

?有了思路,畫圖獨(dú)立完成代碼,不要直接看博主的代碼。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128]={0};
        int left=0,right=0,len=0;
        int n=s.size();
        while(right<n)
        {
            hash[s[right]]++;//進(jìn)入窗口
            while(hash[s[right]]>1)//判斷
                hash[s[left++]]--;//離開窗口
            len=max(len,right-left+1);//更新結(jié)果
            right++;
        }
        return len;
    }
};

3.最大連續(xù)1的個(gè)數(shù)Ⅲ

1004. 最大連續(xù)1的個(gè)數(shù) III - 力扣(LeetCode)https://leetcode.cn/problems/max-consecutive-ones-iii/description/

給定一個(gè)二進(jìn)制數(shù)組?nums?和一個(gè)整數(shù)?k,如果可以翻轉(zhuǎn)最多?k?個(gè)?0?,則返回?數(shù)組中連續(xù)?1?的最大個(gè)數(shù)?。

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

?雖然題目中說是要翻轉(zhuǎn)數(shù)字,但我們要的最終結(jié)果與翻轉(zhuǎn)無關(guān),何況如果真的實(shí)現(xiàn)翻轉(zhuǎn)反而變得復(fù)雜,所以這里我們沒有必要真的翻轉(zhuǎn)。

仔細(xì)閱讀題目,其實(shí)就是求數(shù)組中?段最長(zhǎng)的連續(xù)區(qū)間,要求這段區(qū)間內(nèi) 0 的個(gè)數(shù)不超過 k 個(gè)。

既然是連續(xù)區(qū)間,可以考慮使用『 滑動(dòng)窗口』來解決問題。

思路:

設(shè)置一個(gè) 0 計(jì)數(shù)器 zero。

如果 right 遇到 0,我們應(yīng)該讓 zero ++ ,如果 right 遇到 1,直接跳過即可,這就是『 進(jìn)入窗口』。

判斷什么呢?當(dāng)然是『 判斷』zero是否超過 k,如果超過 就『 離開窗口』,每輪『 更新結(jié)果』。

?有了思路,畫圖獨(dú)立完成代碼,不要直接看博主的代碼。

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int left=0,right=0,zero=0;
        int n=nums.size();
        int ret=0;
        while(right<n)
        {
            if(nums[right]==0)//進(jìn)入窗口
                zero++;
            while(zero>k)//判斷
            {
                if(nums[left++]==0)//離開窗口
                    zero--;
            }
            ret=max(ret,right-left+1);//更新結(jié)果
            right++;
        }
        return ret;
    }
};


4.將 x 減到 0 的最小操作數(shù)(medium)

1658. 將 x 減到 0 的最小操作數(shù) - 力扣(LeetCode)https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/description/

給你一個(gè)整數(shù)數(shù)組?nums?和一個(gè)整數(shù)?x?。每一次操作時(shí),你應(yīng)當(dāng)移除數(shù)組?nums?最左邊或最右邊的元素,然后從?x?中減去該元素的值。請(qǐng)注意,需要?修改?數(shù)組以供接下來的操作使用。

如果可以將?x?恰好?減到?0?,返回?最小操作數(shù)?;否則,返回?-1?。

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

閱讀題目后,我們發(fā)現(xiàn)解決方案可能比較復(fù)雜,因?yàn)榧扔锌赡軓淖竺?,也有可能從右面,還有可能一左一右等等,這么多復(fù)雜的情況,所以我們需要嘗試對(duì)問題做轉(zhuǎn)化,這也就是『 正難則反』的思路。?

【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一),算法,算法,c++

如上圖,我們可以求?target 這一區(qū)域最長(zhǎng)時(shí),那么此時(shí)就對(duì)應(yīng)著最小操作數(shù),最小操作數(shù)就等于數(shù)組元素個(gè)數(shù)減去target區(qū)域的元素個(gè)數(shù)。

所以我們成功轉(zhuǎn)化出『 滑動(dòng)窗口』問題。

  • 如果?sum < target ,右移右指針,直至變量和大于等于 target ,或右指針已經(jīng)移到頭;
  • 如果?sum > target ,右移左指針,直至變量和小于等于?target ,或左指針已經(jīng)移到頭;
  • 如果經(jīng)過前兩步的左右移動(dòng)使得?sum == target ,維護(hù)滿足條件數(shù)組的最大長(zhǎng)度,并讓下個(gè)元素進(jìn)入窗口;

?有了思路,畫圖獨(dú)立完成代碼,不要直接看博主的代碼。

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int sum=0;
        for(int a : nums)
        {
            sum+=a;
        }
        int target = sum-x;
        if(target<0) return -1;//處理細(xì)節(jié)
        int left=0,right=0,tmp=0;
        int n=nums.size();
        int len=-1;
        while(right<n)
        {
            tmp+=nums[right];//進(jìn)入窗口
            while(tmp > target)//判斷
                tmp-=nums[left++];//離開窗口
            if(tmp==target)
                len=max(len,right-left+1);//更新結(jié)果
            right++;
        }
        if(len==-1) return len;
        else return n-len;
    }
};

=========================================================================

如果你對(duì)該系列文章有興趣的話,歡迎持續(xù)關(guān)注博主動(dòng)態(tài),博主會(huì)持續(xù)輸出優(yōu)質(zhì)內(nèi)容

??博主很需要大家的支持,你的支持是我創(chuàng)作的不竭動(dòng)力??

??~ 點(diǎn)贊收藏+關(guān)注 ~??

=========================================================================

到了這里,關(guān)于【算法】基礎(chǔ)算法002之滑動(dòng)窗口(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 算法習(xí)題之滑動(dòng)窗口

    滑動(dòng)窗口是什么? 滑動(dòng)窗口是一種想象出來的數(shù)據(jù)結(jié)構(gòu): 滑動(dòng)窗口有左邊界L和有邊界R 在數(shù)組或者字符串或者一個(gè)序列上,記為S,窗口就是S[L…R]這一部分 L往右滑意味著一個(gè)樣本出了窗口,R往右滑意味著一個(gè)樣本進(jìn)了窗口 L和R都只能往右滑 滑動(dòng)內(nèi)最大值和最小值的更新結(jié)

    2023年04月15日
    瀏覽(26)
  • 【滑動(dòng)窗口、矩陣】算法例題

    【滑動(dòng)窗口、矩陣】算法例題

    目錄 ?三、滑動(dòng)窗口 30. 長(zhǎng)度最小的子數(shù)組?② 31. 無重復(fù)字符的最長(zhǎng)子串?② 32. 串聯(lián)所有單詞的子串?③ 33. 最小覆蓋子串?③ 四、矩陣 34. 有效的數(shù)獨(dú)?② 35. 螺旋矩陣?② 36. 旋轉(zhuǎn)圖像?② 37. 矩陣置零?② 38. 生命游戲?② ?給定一個(gè)含有? n ? 個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù)?

    2024年04月14日
    瀏覽(86)
  • 【優(yōu)選算法】—— 滑動(dòng)窗口類問題

    【優(yōu)選算法】—— 滑動(dòng)窗口類問題

    本期,我給大家?guī)淼氖顷P(guān)于滑動(dòng)窗口類算法的介紹,并通過具體的題目幫助大家思考理解。 ? ? 目錄 (一)基本概念 (二)題目講解 1、難度:medium 1??長(zhǎng)度最小的子數(shù)組 2??找到字符串中所有字?異位詞 2、難度:hard 1??最?覆蓋?串 2??串聯(lián)所有單詞的?串 總

    2024年02月02日
    瀏覽(24)
  • 【算法優(yōu)選】 滑動(dòng)窗口專題——壹

    基本概念 滑動(dòng)窗口是一種 基于雙指針 的一種思想,兩個(gè)指針指向的元素之間形成一個(gè)窗口。 分類:窗口有兩類,一種是 固定大小類 的窗口,一類是 大小動(dòng)態(tài)變化 的窗口。 給定一個(gè)含有 n 個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù) target 。 找出該數(shù)組中滿足其總和大于等于 target 的長(zhǎng)

    2024年02月08日
    瀏覽(21)
  • 算法專題二:滑動(dòng)窗口

    算法專題二:滑動(dòng)窗口

    長(zhǎng)度最小的子數(shù)組 思路一: 思路二: 無重復(fù)字符的最長(zhǎng)子串 思路一: 最大連續(xù)1的個(gè)數(shù) 開頭位0 并且k為0算是一個(gè)特殊的情況這樣的情況有一些考慮就走不出去前面的0而忽略到后面數(shù)組自帶1,走不到這些1數(shù)據(jù)導(dǎo)致記錄連續(xù)1的個(gè)數(shù)出問題! 將x減小到0的最小操作數(shù) 水果成籃

    2024年02月02日
    瀏覽(26)
  • 算法筆記--滑動(dòng)窗口

    算法筆記--滑動(dòng)窗口

    力扣209.長(zhǎng)度最小子數(shù)組 https://leetcode.cn/problems/minimum-size-subarray-sum/ 在這道題中要注意的不僅僅是滑動(dòng)窗口的問題,更重要的問題是在循環(huán)控制中,不恰當(dāng)?shù)恼Z(yǔ)法使用會(huì)導(dǎo)致這道題出現(xiàn)很嚴(yán)重的問題,這導(dǎo)致我做這道題做了很多天,真的很崩潰。 先來看一下循環(huán)的控制問題,

    2024年02月11日
    瀏覽(28)
  • 【算法系列篇】滑動(dòng)窗口

    【算法系列篇】滑動(dòng)窗口

    前面我們學(xué)習(xí)了什么是雙指針,今天我將為大家分享一種特殊的雙指針——滑動(dòng)窗口,為什么說它是特殊的雙指針呢?因?yàn)樗彩怯袃蓚€(gè)指針維護(hù)的,并且兩個(gè)指針的移動(dòng)方向是相同的,就跟我們平時(shí)生活中的窗口一樣,兩條邊是往相同的方向移動(dòng)的。 滑動(dòng)窗口算法是一種用

    2024年02月12日
    瀏覽(16)
  • 「算法」滑動(dòng)窗口

    「算法」滑動(dòng)窗口

    算法需要多刷題積累經(jīng)驗(yàn),所以我行文重心在于分析解題思路,理論知識(shí)部分會(huì)相對(duì)簡(jiǎn)略一些 滑動(dòng)窗口屬于雙指針,這兩個(gè)指針是 同向前行 ,它們所夾的區(qū)間就稱為“窗口” 啥時(shí)候用滑動(dòng)窗口? 題目涉及到“子序列”、“子數(shù)組”、“子串”等概念,要你求和它們相關(guān)的

    2024年02月20日
    瀏覽(19)
  • 【滑動(dòng)窗口】算法實(shí)戰(zhàn)

    【滑動(dòng)窗口】算法實(shí)戰(zhàn)

    滑動(dòng)窗口 ,顧名思義,就是有一個(gè)大小可變的窗口,左右兩端方向一致的向前滑動(dòng) ( 右端固定,左端滑動(dòng);左端固定,右端滑動(dòng) )。 滑動(dòng)窗口的本質(zhì)其實(shí)也是一種雙指針?biāo)惴?,它是根?jù) 單調(diào)性 的思想,使用” 同向雙指針 “,索引字符串或者列表中的一個(gè)區(qū)間 [left,rig

    2024年02月15日
    瀏覽(18)
  • 【算法|數(shù)組】滑動(dòng)窗口

    【算法|數(shù)組】滑動(dòng)窗口

    給定一個(gè)含有 n 個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù) target 。 找出該數(shù)組中滿足其和 ≥ target 的長(zhǎng)度最小的 連續(xù)子數(shù)組 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其長(zhǎng)度**。**如果不存在符合條件的子數(shù)組,返回 0 。 示例 1: 示例 2: 示例 3: 暴力解法 這種做法可以很容易想到,可是誰(shuí)

    2024年02月12日
    瀏覽(16)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包