滑動窗口系列-Leetcode 992. K 個不同整數的子數組

問題描述

給定一個正整數數組 A,如果 A 的某個子數組中不同整數的個數恰好爲 K,則稱 A 的這個連續、不一定獨立的子數組爲好子數組。

(例如,[1,2,3,1,2] 中有 3 個不同的整數:1,2,以及 3。)

返回 A 中好子數組的數目。

示例 1:

輸入:A = [1,2,1,2,3], K = 2
輸出:7
解釋:恰好由 2 個不同整數組成的子數組:[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].

解題報告

考慮累加以每個數字結尾的好子數組的個數。
那麼如何計算以每個數字結尾的子數組的個數呢?
假設 [r,i] 是以 A[i] 結尾的好數組的最小區間,[l,i] 是以 A[i] 結尾的好數組的最大區間,
則每個累加 r-l+1 即可。
所以現在問題變成了 如何計算 lr
l 意味着 [l,i] 的區間中不同整數的個數取不到 K+1 時,不開始更新 l
r 意味着 [r,i] 的區間中不同整數的個數剛取到 K 時,開始更新 r

想法其實挺簡單的,但是編碼實現時,總是不知如何下手,哎,還是要多多練習吧

這題和 Leetcode 1248. 統計「優美子數組」 的【滑動窗口解法】有着異曲同工之妙,只是 Leetcode 1248 中,數組中只有兩類數,奇數&偶數,所以我們不需要令設兩個數組來記錄窗口內的奇數和偶數。

實現代碼

代碼部分完全源自參考的文獻,侵權必刪

class Solution{
    public:
        int subarraysWithKDistinct(vector<int>&A, int K){
            int n=A.size();
            vector<int>cl(n+1, 0), cr(n+1, 0);
            int l=0, r=0, ans=0, nl=0, nr=0;
            for(int i=0;i<n;i++){
                if(cl[A[i]]++==0) nl++;
                while(nl>K){
                    if(--cl[A[l++]]==0) nl--;
                }
                if(cr[A[i]]++==0) nr++;
                while(nr>=K){
                    if(--cr[A[r++]]==0) nr--;
                }

                ans+=(r-l);
            }
            return ans;
        }
};

參考資料

[1] Leetcode 992. K 個不同整數的子數組
[2] 每日算法系列【LeetCode 992】K個不同整數的子數組
[3] Leetcode 1248. 統計「優美子數組」
[4] Leetcode 1248. 統計「優美子數組」【記錄奇數位置&滑動窗口&前綴和】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章