双指针算法,首先想想暴力怎么做
for(int i=0;i<nums.size();i++)
{
long long sum=1;
for(int j=i;j<nums.size();j++)
{
sum*=nums[j];
if(sum<k) res++;
if(sum>=k) break;
}
}
双指针算法维护区间信息,通常是需要找出一定的单调性,使得对于区间内的数据增减都比较方便,我们其实可以发现,子数组的积就具有单调性(元素一定>=1)
本题的要求:找出所有子数组积小于k的区间
特殊情况:子数组积可能小于区间内某个数
第一种做法 (固定左端点考虑)
这种做法其实是存在一定弊端的,因为k不可能<=序列中的任意一个数,否则会错误
for(int i=0,j=0;i<nums.size();)
{
while(j<nums.size()&&sum*nums[j]<k)
sum*=nums[j],j++;
res+=j-i;
sum/=nums[i];
i++;
}
第二种做法(固定右端点考虑)
由于k可能很小,如果要用sum单调递增的办法是很难做的,可以试试sum单调递减的办法
*上所有遍历到的nums[i],然后
- sum>=k时,固定右端点,右移左端点,达到缩小窗口的作用
- sum<k,固定右端点,查看窗口内以该端点为右端点的区间数
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int res=0;
long long sum=1;
if(k == 0)
return 0;
for(int i=0,j=0;i<nums.size();)
{
sum*=nums[i];
while(j<=i&&sum>=k)
sum/=nums[j++];
res+=i-j+1;
i++;
}
return res;
}
};