前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >滑动窗口之乘积小于k的子数组

滑动窗口之乘积小于k的子数组

作者头像
xinxin-l
发布2022-03-30 16:09:12
7110
发布2022-03-30 16:09:12
举报

713. 乘积小于k的子数组

给定一个正整数数组 nums和整数 k 。 请找出该数组内乘积小于 k 的连续的子数组的个数。

先敲个黑板

下面一共有两种写法,第一种是按自己理解写的,是过了的,但是 感觉懂了但没完全懂。。。(意思是 我好像懂了滑动窗口 但是写的不规律不条理 好像没完全懂。。);第二种是更条理的解法,有助于更好的理解~

如果想直接看详细讲解(唠叨)的,可以直接跳过这段代码看下面的分析哦~~~

第一种

第一种就不讲解了哈,可以看完下面的分析来看这段代码,其实也挺好理解的~

代码语言:javascript
复制
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var numSubarrayProductLessThanK = function(nums, k) {
    let l=0,r=0;
    let n=nums.length;
    let ans=0;
    let tem=1;
    while(r<n){
        if(l===r){
            if(nums[l]<k){
                ans++;
                r++;
                tem=nums[l]*nums[r];
            }else{
                l++,r++;
            }
        }else{
            while(tem<k && r<n){
                ans=ans+r-l+1;
                r++;
                tem=tem*nums[r];
            }
            l++;
            tem=tem/(nums[l-1]);
        }
    }
    return ans;
};

第二种

首先解释一下,下面的n是指数组长度,k是指乘积需要小于的那个数,ans是指要求解的子数组的个数,l、r是指左右指针。下面的分析比较侧重于推敲思路,可能言语上会有不严谨的地方,大家就当作参考咯(逃!

这种解法同样是 刚开始左右指针指在同一个地方,然后由于乘积小于k,r可以向右移动,乘积继续变化,直到乘积大于等于k,我们就需要进行一些操作了。

我们可以想一想,只要r小于n,那当r每次增加1的时候,我们就可以计算ans,将ans+r-l+1,诶,为什么是r-l+1呢? 因为我们计算的是连续的子数组的个数,每次右指针移动、加入一个新的右边的数值的时候,在满足l到r的乘积小于k的前提下,总的ans的增加量就是新的值、新的值与之前所有可连续的值的组合,这个就用到一点点数学知识了~

那计算ans的时候l难道一直是1吗? 不,l是会变化的(排除极端情况),那l什么时候变呢? l变了之后ans又会是多少呢?

让我们来想一想,我们需要满足的条件是连续数组内的数乘积小于k,当右指针一直向右移动使得乘积不断增大时,总会有大于等于k的时候,那个时候,我们就需要改变l了,在这种情况下,我们计算的ans就不是现在的r-l+1了,因为r指向的值不满足条件,我们需要在改变l之后再去求ans

那l会发生什么样的改变呀,l会向右移动多少呢?

因为当l不变、r向右移动时,我们的乘积一直都是非递减的,如果当前右指针移动到的位置使得l到r不满足乘积小于k,那我们再继续移动右指针,乘积一定依旧不满足小于k,那就说明这个l我们已经“利用”完了,l可以退出滑动窗口了~

所以l的改变就取决于乘积除以要移除的nums[l]的结果,直到这个结果小于k时,l就不需要再变化了

这个时候我们就能求取当前的l到r对应的ans值了(因为已经满足乘积小于k这个条件了)

代码语言:javascript
复制
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var numSubarrayProductLessThanK = function(nums, k) {
    if(k===0||k===1){return 0}
    let l=0,r=0;
    let n=nums.length;
    let ans=0;
    let tem=1;
    while(r<n){
        tem=tem*nums[r];

        while(tem>=k){
            tem=tem/(nums[l]);
            l++;
        }

        ans=ans+r-l+1;
        r++;
    }
    return ans;
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 713. 乘积小于k的子数组
  • 先敲个黑板
  • 第一种
  • 第二种
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档