滑动窗口(十五)2962. 统计最大元素出现至少 K 次的子数组(越长越合法型)

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

给你一个整数数组 nums 和一个 正整数 k

请你统计有多少满足 「 nums 中的 最大 元素」至少出现 k 次的子数组,并返回满足这一条件的子数组的数目。

子数组是数组中的一个连续元素序列。

示例 1:

复制代码
输入:nums = [1,3,2,3,3], k = 2
输出:6
解释:包含元素 3 至少 2 次的子数组为:[1,3,2,3]、[1,3,2,3,3]、[3,2,3]、[3,2,3,3]、[2,3,3] 和 [3,3] 。

示例 2:

复制代码
输入:nums = [1,4,2,1], k = 3
输出:0
解释:没有子数组包含元素 4 至少 3 次。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 106
  • 1 <= k <= 105

首先使用N^2的方法,固定左端点,枚举所有的子数组,然后看他们中最大值出现的次数如果大于k就++

优化:发现当cnt为k的时候,后续就不需要处理了,直接把j后面所有的值用n-j+1就能加入结果中

优化:再次优化,发现之前的j不需要每次都从当前i这个位置进行后续判断,可以采用滑动窗口的思想去处理这个题目,j不需要回退

之前写的题都是控制右窗口,这次使用控制左窗口,固定左边界,

cpp 复制代码
class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long res = 0;
        int mx = *max_element(nums.begin(), nums.end()); // 获取数组中的最大值
        int cnt = 0, n = nums.size();
        for(int i = 0, j = 0; i < n; i++) // 控制左端点
        {
            while(j < n && cnt < k)  // 进窗口
            {                        // 让j去往右访问,当j到达边界或者最大值出现了k次时停下
                if(nums[j] == mx)
                    cnt++;
                j++;
            }
            if(cnt == k)
                res += n-j+1;        // 维护结果 j之后的所有数组都满足条件
            if(nums[i] == mx)        // 出窗口 左端点进行出窗口
                cnt--;
        }
        return res;
    }
};

采用固定右边界的方式:不需要一些多余的判断

cpp 复制代码
class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        // unordered_map<int,int> window;
        int left = 0, right = 0, n = nums.size();
        int cnt = 0, mx = *max_element(nums.begin(), nums.end());
        long long res = 0;
        while(right < n)  // 这次采用固定右端点,维护所有左边界
        {
            if(nums[right] == mx) // 入窗口
                cnt++;
            while(cnt >= k)        // left到right内部都是符合条件的
            {                       // 所以让left到达一个临界点
                if(nums[left] == mx)
                    cnt--;
                left++;
            }
            res += left;     // 保存left之前所有符合条件的结果
            right++;
        }
        return res;
    }
};

由于子数组越长,包含的元素越多,越能满足题目要求;反之,子数组越短,包含的元素越少,越不能满足题目要求。有这种性质的题目,可以用滑动窗口解决。

相关推荐
小蒋学算法19 小时前
算法-M个非重叠子数组最大和II-WQS二分学习
数据结构·学习·算法
我要见SA姐119 小时前
AI提示词遇见精密算法:TimeGuessr如何用数学魔法打造文化游戏新体验
人工智能·算法·游戏
Jerry20 小时前
LeetCode 56. 合并区间
算法
实验如有神祝女士1 天前
不同参数规模大模型在医学翻译场景的适配差异
论文阅读·人工智能·深度学习·学习·算法·语言模型·论文笔记
windliang1 天前
Claude Code 源码分析(三):一次模型回答如何流进 Agent
前端·算法·ai编程
Kyrie_kk1 天前
Java--BigInteger 超大整数计算
java·算法
神明不懂浪漫1 天前
【第三章】链表
开发语言·数据结构·经验分享·笔记·链表
汽车网络安全爱好者1 天前
Public Key Infrastructure(二)— 深入理解 X.509 证书:从 RFC 5280 到 OpenSSL 实践
运维·服务器·算法·网络安全·汽车·密码学·可信计算技术
tkevinjd1 天前
力扣131-分割回文串
算法·leetcode·深度优先
BioRunYiXue1 天前
技术干货 | LiP-MS全流程解析:从实验设计到数据分析
大数据·前端·javascript·人工智能·算法·数据挖掘·数据分析