1. 程式人生 > 其它 >[可變滑動視窗]力扣209. 長度最小的子陣列 713. 乘積小於 K 的子陣列

[可變滑動視窗]力扣209. 長度最小的子陣列 713. 乘積小於 K 的子陣列

209. 長度最小的子陣列

給定一個含有 n 個正整數的陣列和一個正整數 target 。

找出該陣列中滿足其和 ≥ target 的長度最小的 連續子陣列 [numsl, numsl+1, ..., numsr-1, numsr] ,並返回其長度如果不存在符合條件的子陣列,返回 0 。

示例 1:

輸入:target = 7, nums = [2,3,1,2,4,3]
輸出:2
解釋:子陣列 [4,3] 是該條件下的長度最小的子陣列。

示例 2:

輸入:target = 4, nums = [1,4,4]
輸出:1

示例 3:

輸入:target = 11, nums = [1,1,1,1,1,1,1,1]
輸出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

題解

使用l,r表示視窗的左右端,初始化都為0,res記錄最小長度(初始化為最大長度+5),sums記錄視窗內元素的和

1.r不斷右移動,擴大視窗,sums隨之累計,判斷sumstarget的大小,如果sums大於target,執行2.

2.l不斷右移動,縮小視窗,sums減去相應的元素的值,同時更新res的值,resmin(res,r-l+1)r-l+1為此時視窗大小(子陣列長度)

在返回結果前判斷,res是否為初始化的值,如果為,說明沒有符合條件子陣列,應該返回0,否則返回res

程式碼
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=nums.size();
        //r初始化為最大長度+5
        int l=0,r=0,sums=0,res=100005;
        while(r<len){
            sums+=nums[r];//更新
            while(sums>=target){
                //更新res
                res=res>(r-l+1)?(r-l+1):res;
                sums-=nums[l++];//更新
            }
            r++;
        }
        //如果res沒變就輸出0
        return res==100005?0:res;
    }
};

713. 乘積小於 K 的子陣列

給你一個整數陣列 nums 和一個整數 k ,請你返回子陣列內所有元素的乘積嚴格小於 k 的連續子陣列的數目。

示例 1:

輸入:nums = [10,5,2,6], k = 100
輸出:8
解釋:8 個乘積小於 100 的子陣列分別為:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
需要注意的是 [10,5,2] 並不是乘積小於 100 的子陣列。

示例 2:

輸入:nums = [1,2,3], k = 0
輸出:0

提示: 

  • 1 <= nums.length <= 3 * 104
  • 1 <= nums[i] <= 1000
  • 0 <= k <= 106

題解

此題與上題類似,但是不能直接套,依舊使用l,r表示視窗左右端,初始化都為0,cnt記錄總個數,res表示視窗內元素的乘積

如果視窗內元素為1,2,3,4滿足<k,則視窗不需要收縮了,因為視窗元素滿足<k則其子集也滿足乘積<k,

所以只需要找到剛好滿足條件的視窗,r-l+1得到長度即為此視窗內元素所有滿足條件的子陣列個數。

如何找到剛好滿足條件的視窗?

1.r不斷右移動,擴大視窗,res不斷累乘,進行2.,然後判斷res是否滿足<k,滿足則cnt+=r-l+1,cnt累加當前窗口裡所有可能的子陣列數目

2.判斷res是否>k,如果大於,則視窗還不滿足條件,l右移動,縮小視窗,同時res也減小,直到視窗滿足條件或l>r終止

程式碼

class Solution {
public:
    int numSubarrayProductLessThanK(vector<int>& nums, int k) {
        int len=nums.size();
        int l=0,r=0,res=1,cnt=0;
        while(r<len){
            res*=nums[r];
            while(res>=k&&l<=r){
                res/=nums[l++];
            }
            if(res<k)
                cnt+=r-l+1;
            r++;
           
        }
        return cnt;
    }
};