滑动窗口(十五)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;
    }
};

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

相关推荐
devnullcoffee20 小时前
2026年Amazon Listing优化完全指南:COSMO算法与Rufus AI技术解析
人工智能·python·算法·亚马逊运营·amazon listing·cosmo算法·rufus ai技术
苦藤新鸡20 小时前
19.旋转输出矩阵
c++·算法·leetcode·力扣
zsffuture20 小时前
RKNN 8位量化全解析:算法差异与粒度选择实战指南
算法
玄冥剑尊20 小时前
贪心算法深化 II
算法·贪心算法
Pluchon21 小时前
硅基计划4.0 算法 动态规划入门
java·数据结构·算法·动态规划
玄冥剑尊21 小时前
贪心算法深化 III
算法·贪心算法
txinyu的博客21 小时前
list 三个经典版本
数据结构·list
wen__xvn21 小时前
算法刷题目录
算法
Tisfy21 小时前
LeetCode 1292.元素和小于等于阈值的正方形的最大边长:二维前缀和(无需二分)+抽象速懂的描述
算法·leetcode·职场和发展
老了,不知天命21 小时前
離散數學複習
数据结构·物理·筆記·數學