LeetCode 第993題 Subarrays with K Different Integers【滑動視窗】(Java)
原題地址: https://leetcode.com/problems/subarrays-with-k-different-integers/
要求如下:
給定一個正整數的陣列,尋找(連續,但是元素不一定不重複的)子陣列,滿足條件就是裡面不同的數字的數量,正好是K個。
例如[1,2,3,1,2]有三個不同的數字,1,2,3。
要求返回這樣的子陣列的數量。
例 1:
輸入: A = [1,2,1,2,3], K = 2
輸出: 7
正好有兩個數字的子陣列包括 [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2],7個。
例 2:
輸入:A = [1,2,1,3,4], K = 3
輸出: 3
正好三個數字的子陣列包括[1,2,1,3], [2,1,3], [1,3,4]。
注意:
1 <= A.length <= 20000
1 <= A[i] <= A.length
1 <= K <= A.length
前面幾道題,我都是獨立做出來的,但是992題,我看了leetcode的解題,還看了youtube的視訊(見參考文獻)。在我研究滑動視窗演算法之前,這道題我還做過暴力解,應該是對的,但是速度有點慢,在leetcode上面提交的時候timeout了。
我學習了leetcode提供的解答和youtube視訊的解法,但是我都自己實現了一遍。
這個題目的難度在於,一開始我一直想用一個滑動視窗解開,但是發現很難。後來,我看了 leetcode 的解法,其實要點就是用了兩個視窗。
首先我們會發現包含的字元數正好等於K很難做,但是字元數小於等於K相當好做。首先left和right都為0,以例1為例。逐步移動right,這時候從0開始一直到3,包含的字元都是小於2的,然後移動left,直到字元數小於K,也就是隻有一個字元,在這個過程中,每一個left和right的組合都是合法的。然後繼續移動right到最後,然後一步步移動left直到字元數小於K。所以,這是一個常規的演算法。
演算法如下,字元數小於等於K:

如果,字元數小於等於K的函式 subarraysWithMostKDistinct 定義出來了。
那麼subarraysWithMostKDistinct(k) – subarraysWithMostKDistinct(k-1)不就是正好等於K的結果麼?
所以結果函式寫為:

這個實際上是youtube上的解法。但是,我們在仔細一想,leetcode上面的解法,其實跟這個是一個意思。只不過,leetcode解法,把兩次呼叫mostk改成了一個是mostk的left指標和一個mostk-1的指標而已。程式碼如下,這個題感覺很繞,但是想通了,程式碼並不複雜(我的看起來複雜是因為我特意寫成跟leetcode不一樣的形式來驗證我是不是自己可以重新寫得出來。leetcode的程式碼形式很簡潔。):

本題程式碼地址為: https://github.com/tinyfool/leetcode/tree/master/src/p0992
本文假設你對滑動視窗概念有所瞭解,如果你對滑動視窗的概念不夠了解,請參看我介紹 滑動視窗的文章,裡面有詳細的解釋 。
參考文獻: