关于双指针问题,前面链表部分介绍过快慢指针的问题,而双指针还有一种情况,也就是滑动指针,正好,最近字节跳动青训营出了类似的题目,正式来自力扣的713题
而青训营中特别要求满足时间复杂度为O(n),
这个题目,我一开始是这样想的,搞两个指针,一个左一个右,开始都位于数组开始的位置,右指针往后走一步,计算一步,直到不满足条件为止,然后left++再次重头再来。
代码:
int numSubarrayProductLessThanK(int* nums, int numsSize, int k)
{
if(k<=0)
return 0;
int left=0;
int right=0;
int a=0;
int count=0;
while(left<numsSize)
{
right=left;
count=nums[left++];
for(int right=left;count<k;right++)
{
a++;
if(right>=numsSize)
{
break;
}
count*=nums[right];
}
}
return a;
}
但是这样的代码时间复杂度很明显是O(n2),虽然力扣能够通过,但是,不够厉害,而这时滑动窗口才是最优的算法。
这种算法的奇妙之处在于,如果前面这么多数乘起来还小,那么继续移动right,而如果这些数乘起来超过了那个k,则去移动left,这样,无论是left,还是right,都是只遍历了一次这个数组,时间复杂度自然是2O(N)也可以简化成O(N)
int numSubarrayProductLessThanK(int* nums, int numsSize, int k)
{
if(k<=1)
return 0;
int l=0,r=0,sum=1,cnt=0;
for(r=0;r<numsSize;r++)
{
sum*=nums[r];
while(sum>=k)
sum/=nums[l++];
cnt+=r-l+1;
}
return cnt;
}