[可變滑動視窗]力扣209. 長度最小的子陣列 713. 乘積小於 K 的子陣列
阿新 • • 發佈:2022-05-29
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
隨之累計,判斷sums
與target
的大小,如果sums
大於target
,執行2.,
2.l
不斷右移動,縮小視窗,sums
減去相應的元素的值,同時更新res
的值,res
取min(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;
}
};