当前位置: 首页 > news >正文

力扣992做题笔记

左神做法的理论依据

我们可以通过 集合的包含关系具体示例枚举 来直观理解这一推导过程。以下结合题目示例 1 进行详细说明:

示例 1 分析

输入nums = [1,2,1,2,3], k = 2
目标:计算恰好包含 2 种不同整数 的子数组个数。

步骤一集合 A 的计数

滑动窗口的核心逻辑是:

  • 对于每个右边界 r,找到最小左边界 l,使得窗口 [l, r] 内不同整数个数 ≤k。
  • 此时,左边界可以是 [l, r] 中的任意位置,因此贡献 r - l + 1 个子数组。

以示例 1 为例,滑动窗口计算 findNumsofMost(nums, 2)(即 |A|)的过程如下:

r元素窗口内元素不同数最小左边界 l贡献子数组数
01[1]101
12[1,2]202
21[1,2,1]203
32[1,2,1,2]204
43[2,1,2,3]3(超过 2)移动 l 到 1窗口 [1,4] 含 2,1,3(3 种,仍超过)→ 继续移动 l 到 2 → 窗口 [2,4] 含 1,2,3(3 种,仍超过)→ 移动 l 到 3 → 窗口 [3,4] 含 2,3(2 种)→ 最小 l=3,贡献 (4-3+1=2)

累加结果:(1+2+3+4+2=12),即 |A|=12。
findNumsofMost(nums, 1)(即 |B|)的计算结果为 5(仅含单个元素的子数组),因此:

步骤 2:定义集合 B(不超过 k-1 种)

集合 B 包含所有不同整数个数 ≤1 的子数组(即仅含 1 种整数)。
枚举所有满足条件的子数组:

  • 单个元素:[1], [2], [1], [2], [3],共 5 个。
  • 连续相同元素的子数组:
    • [1](位置 0)、[2](位置 1)、[1](位置 2)、[2](位置 3)、[3](位置 4)。
    • 无长度 ≥2 的连续相同元素(因为数组中相邻元素不同)。
  • 集合 B 的总数:5 个。
步骤 3:计算集合差集 A - B

根据定义:
恰好含 k 种的子数组个数 = |A| - |B|

  • 集合 A 包含 含 1 种或 2 种 的子数组。

  • 集合 B 包含 仅含 1 种 的子数组。

  • 因此,A - B 即为仅含 2 种的子数组,其数量为:
    |A| - |B| = 12 - 5 = 7

    这与题目示例 1 的输出一致。

数学推导:集合差集的严格性

  • 设 (f(m)) 表示 不同整数个数 ≤m 的子数组个数。

  • 恰好含 k 种的子数组必须满足:

    • 不同整数个数 ≤k(属于集合 A),
    • 且不同整数个数 >k-1(不属于集合 B)。
  • 因此,恰好含 k 种的子数组是 A 中排除 B 的部分,即:

    = f(k) - f(k-1)

例子 2:更简单的数组(nums = [1,1,2], k=2)

为了更直观,我们用一个更短的数组验证。

问题目标

找到所有「恰好有 2 种不同整数」的子数组。

数组分析

数组 [1,1,2] 的所有子数组及其不同整数个数:

子数组内容不同整数个数
[0,0][1]1
[0,1][1,1]1
[0,2][1,1,2]2
[1,1][1]1
[1,2][1,2]2
[2,2][2]1
集合 A(≤2)和 B(≤1)的大小
  • 集合 A(≤2):所有子数组都满足(因为最大不同个数是 2),共 6 个。
  • 集合 B(≤1):不同整数个数为 1 的子数组,即 [0,0], [0,1], [1,1], [2,2] → 共 4 个。
结论验证

恰好有 2 种不同整数的子数组是 [0,2], [1,2] → 共 2 个。
根据公式 |A| - |B| = 6 - 4 = 2,与实际结果一致。

数学推导:为什么差集是正确的?

用数学符号形式化定义:

  • f(k) 为「不同整数个数 ≤k 的子数组数目」。
  • g(k) 为「不同整数个数恰好等于k 的子数组数目」。

根据定义,f(k) 是所有 g(1), g(2), ..., g(k) 的和,即:
[ f(k) = g(1) + g(2) + … + g(k) ]

同理,f(k-1) 是:
[ f(k-1) = g(1) + g(2) + … + g(k-1) ]

两式相减得:
[ f(k) - f(k-1) = g(k) ]

这正是题目要求的「恰好有k种不同整数的子数组数目」。

总结

通过具体例子和数学推导可以看出:
「不超过k的子数组数」减去「不超过k-1的子数组数」,本质是通过「前缀和相减」的方式,精准提取出「恰好等于k」的子数组数目。这种方法将复杂的「恰好k」问题转化为更易计算的「不超过k」问题,是滑动窗口算法中常用的技巧。

代码

class Solution {public int subarraysWithKDistinct(int[] nums, int k) {return findNumsofMost(nums, k) - findNumsofMost(nums, k - 1); }private static final int maxn = 20001;private static int[] cnts = new int[maxn];private int findNumsofMost(int[] nums, int k) { Arrays.fill(cnts, 1, nums.length + 1, 0);int ans = 0;for (int r = 0, l = 0, collect = 0; r < nums.length; r ++) { if (++cnts[nums[r]] == 1) { collect ++;}while (collect > k) { if (--cnts[nums[l++]] == 0) { collect--;}}ans += r - l + 1;}return ans;}
}

相关文章:

  • SQL注入——Sqlmap工具使用
  • UA 编译和建模入门教程(zhanzhi学习笔记)
  • LLM最后怎么输出值 解码语言模型:从权重到概率的奥秘
  • 手机怎么查看网络ip地址?安卓/iOS设备查询指南
  • 【QT】类A和类B共用类C
  • python实现pdf转图片(针对每一页)
  • React Contxt详解
  • 【计算机主板架构】ITX架构
  • 企业标准信息公共服务平台已开放标准通编辑器访问入口
  • 苹果的人工智能领域慢热
  • 计算机视觉设计开发工程师学习路线
  • 展锐Android14及更新版本split_build编译方法
  • 【android bluetooth 协议分析 01】【HCI 层介绍 9】【ReadLocalSupportedCommands命令介绍】
  • C语言实现android/linux按键模拟
  • Linux动静态库制作与原理
  • 汇编:电子计数器
  • Linux问题排查-找到偷偷写文件的进程
  • 服务器的基础知识
  • 软件设计师完整性约束考点分析——求三连
  • AIGC与文本生成:人工智能写作的新纪元
  • 湛江网站排名提升/长沙百度搜索排名优化
  • 衡水哪个公司做网站好/网站排名优化师
  • 永嘉网站制作系统/百度目前的推广方法
  • 平台网站的策划设计/志鸿优化设计官网
  • 如何在对方网站上做外链/丹东seo推广优化报价
  • 网站建设中的色彩搭配/短视频推广平台