[LeetCode] Subarray Product Less Than K 子陣列乘積小於K
Your are given an array of positive integers nums
.
Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k
.
Example 1:
Input: nums = [10, 5, 2, 6], k = 100 Output: 8 Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]. Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Note:
0 < nums.length <= 50000
.0 < nums[i] < 1000
.0 <= k < 10^6
.
這道題給了我們一個數組和一個數字K,讓我們求子陣列且滿足乘積小於K的個數。既然是子陣列,那麼必須是連續的,所以肯定不能給陣列排序了,這道題好在限定了輸入數字都是正數,能稍稍好做一點。博主剛開始用的是暴力搜尋的方法來做的,就是遍歷所有的子陣列算乘積和K比較,兩個for迴圈就行了,但是OJ不答應。於是上網搜大神們的解法,思路很贊。相當於是一種滑動視窗的解法,維護一個數字乘積剛好小於k的滑動視窗,用變數left來記錄其左邊界的位置,右邊界i就是當前遍歷到的位置。遍歷原陣列,用prod乘上當前遍歷到的數字,然後進行while迴圈,如果prod大於等於k,則滑動視窗的左邊界需要向右移動一位,刪除最左邊的數字,那麼少了一個數字,乘積就會改變,所以用prod除以最左邊的數字,然後左邊右移一位,即left自增1。當我們確定了視窗的大小後,就可以統計子陣列的個數了,就是視窗的大小。為啥呢,比如[5 2 6]這個視窗,k還是100,右邊界剛滑到6這個位置,這個視窗的大小就是包含6的子陣列乘積小於k的個數,即[6], [2 6], [5 2 6],正好是3個。所以視窗每次向右增加一個數字,然後左邊去掉需要去掉的數字後,視窗的大小就是新的子陣列的個數,每次加到結果res中即可,參見程式碼如下:
class Solution { public: int numSubarrayProductLessThanK(vector<int>& nums, int k) { if (k <= 1) return 0; int res = 0, prod = 1, left = 0; for (int i = 0; i < nums.size(); ++i) { prod *= nums[i]; while (prod >= k) prod /= nums[left++]; res+= i - left + 1; } return res; } };
討論:這道題其實可有很多種變形,比如當陣列的數字有負數和0該怎麼做?或者求的不是子陣列,而是子序列該怎麼做,子序列的話就可以排序啦,當然還是需要都是正數,才有排序的意義,博主覺得如果有負數和0,是不是隻能暴力破解了,或者使用Maximum Product Subarray中的方法?再有一種的變形就是求子陣列或子序列乘積剛好等於k,這就跟Subarray Sum Equals K和Maximum Size Subarray Sum Equals k這兩題中使用的方法類似吧,建立子陣列和其乘積之間的對映來快速找到。
歡迎大家在評論區留言討論!
類似題目:
參考資料: