Day61 | 灵神 | 滑动窗口:统计最大元素出现至少K次的子数组

Day61 | 灵神 | 滑动窗口:统计最大元素出现至少K次的子数组

2962.统计最大元素出现至少K次的子数组

2962. 统计最大元素出现至少 K 次的子数组 - 力扣(LeetCode)

思路:

一开始我并没有想出来,这是笔者的代码,很遗憾超时了,因为这个和暴力的思路差不多

class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long l=0,res=0;
        int max_num = ranges::max(nums),max_cnt=0;
        for(int i=0;i<nums.size();i++)
        {
            if(max_num==nums[i])
                max_cnt++;
            int temp=max_cnt;
            while(max_cnt>=k)
            {
                res++;
                if(nums[l]==max_num)
                    max_cnt--;
                l++;
            }
            l=0;
            max_cnt=temp;
        }
        return res;
    }
};

核心思路还是和前面滑动窗口的题一样,都是固定并遍历右端点,然后去寻找左指针收缩的条件。

本题左指针收缩的条件就是当前左右端点区间内的最大值的数量max_cnt大于等于k时,左指针收缩,收缩到当前左右端点区间内的最大值数量max_cnt小于k的时候就可以停止了。

class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long l=0,res=0;
        int max_num = ranges::max(nums),max_cnt=0;
        for(int i=0;i<nums.size();i++)
        {
            if(max_num==nums[i])
                max_cnt++;
            int temp=max_cnt;
            while(max_cnt>=k)
            {
                res++;
                if(nums[l]==max_num)
                    max_cnt--;
                l++;
            }
        }
        return res;
    }
};

一开始并没有下面这两行

l=0;
max_cnt=temp;

后来加上是因为我发现了我的代码的漏洞

比如区间为[1,3,2,3]时,我固定了第二个3,当左指针收缩到第一个3的时候会把max_cnt–,这就导致当区间为[1,3,2,3,3]时,我的max_cnt=2,而不是3。

所以我加上了上面这两行,让右边固定的时候左边从头开始计算。可是这样就和暴力解法的时间复杂度差不多了

问题的核心在于如何统计子数组的数量

如果在max_cnt–之后,仍然不影响统计满足条件的子数组的数量呢?

答案是在循环退出后直接 res+=l

举两个例子

当右端点固定为第二个3,区间为[1,3,2,3],这时左指针往左移动,移动到l=2,即区间为[2,3]时,max_cnt变为1,退出了循环,而满足条件的子数组为[1,3,2,3],[3,2,3],而l正好就是2,因为我们左指针移动过的路径就是所有满足条件的子数组。

再举一个例子:

右端点固定为第3个3,区间为[1,3,2,3,3],这是我们的l从2开始,真实区间其实是[2,3,3],这其实没有关系,因为l的2在这里其实代表的是[1,3,2,3,3]和[3,2,3,3]这两个子数组。然后移动到最后一个数[3],此时l=4,这四个子数组就是[1,3,2,3,3]、[3,2,3,3]、[2,3,3]、[3,3],没错,就是左指针走过的路径长度,即l的大小,所以直接res+=l就记录了子数组的个数.

完整代码:

class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long l=0,res=0;
        int max_num = ranges::max(nums),max_cnt=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==max_num)
                max_cnt++;
            while(max_cnt==k)
            {
                if(nums[l]==max_num)
                    max_cnt--;
                l++;
            }
            res+=l;
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值