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

DeepSeek LeetCode 3261. 统计满足 K 约束的子字符串数量 II Java实现

这道题是 LeetCode 3261. 统计满足 K 约束的子字符串数量 II,要求高效处理多个查询,统计每个查询区间内满足 K 约束的子串数量。

题目回顾

K 约束定义:字符串中 '0' 或 '1' 的个数 不超过 K。

关键难点:需要 O(1) 或 O(log n) 处理每个查询,不能暴力枚举。

解题思路

1. 找到每个位置 i 作为左端点时,最远可以到达的右端点
对于每个左端点 left,找到最大的 right 使得 [left, right] 满足 K 约束。
利用滑动窗口(双指针)在 O(n) 内完成。
2. 构建前缀和数组
设 maxRight[i] = 以 i 为左端点的最大可行右端点(包含)。
对于查询 [l, r],对于左端点 i 在 [l, r] 范围内:
· 如果 maxRight[i] >= r,说明以 i 开头的子串从 i 到 r 都满足,贡献 (r - i + 1) 个。
· 如果 maxRight[i] < r,贡献 (maxRight[i] - i + 1) 个。
但直接遍历会超时,需要优化。
3. 前缀和 + 二分查找优化
由于 maxRight 数组单调不减(可以用滑动窗口证明),我们可以:
· 预处理 prefixSum[i] 表示以 0..i 为左端点的累计子串数。
· 对于查询 [l, r],二分找到最后一个位置 p 使得 maxRight[p] < r。
· 那么:
· 对于左端点 i ∈ [l, p],每个贡献 (maxRight[i] - i + 1)
· 对于左端点 i ∈ [p+1, r],每个贡献 (r - i + 1)
两部分都能用前缀和快速计算。

Java 实现

```java
class Solution {
public long[] countKConstraintSubstrings(String s, int k, int[][] queries) {
int n = s.length();
char[] arr = s.toCharArray();

// 1. 滑动窗口计算 maxRight[i]
int[] maxRight = new int[n];
int[] cnt = new int[2]; // cnt[0] 数0的个数,cnt[1] 数1的个数
int right = 0;
for (int left = 0; left < n; left++) {
while (right < n && (cnt[0] + (arr[right] == '0' ? 1 : 0) <= k ||
cnt[1] + (arr[right] == '1' ? 1 : 0) <= k)) {
cnt[arr[right] - '0']++;
right++;
}
maxRight[left] = right - 1; // 以 left 开头最远可到的位置
// 移除 left 位置的字符,为下一次循环做准备
cnt[arr[left] - '0']--;
}

// 2. 前缀和数组 preSum[i] = sum_{j=0}^{i-1} (maxRight[j] - j + 1)
long[] preSum = new long[n + 1];
for (int i = 0; i < n; i++) {
preSum[i + 1] = preSum[i] + (maxRight[i] - i + 1);
}

// 3. 处理查询
long[] res = new long[queries.length];
for (int idx = 0; idx < queries.length; idx++) {
int l = queries[idx][0];
int r = queries[idx][1];

// 二分查找最后一个位置 p 满足 maxRight[p] < r
int low = l, high = r, p = l - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (maxRight[mid] < r) {
p = mid;
low = mid + 1;
} else {
high = mid - 1;
}
}

long total = 0;
if (p >= l) {
// 左端点 i ∈ [l, p],贡献 (maxRight[i] - i + 1)
total += preSum[p + 1] - preSum[l];
}
if (p + 1 <= r) {
// 左端点 i ∈ [p+1, r],贡献 (r - i + 1)
long len = r - (p + 1) + 1;
total += len * (len + 1) / 2;
}
res[idx] = total;
}
return res;
}
}
```

复杂度分析

· 时间复杂度:O(n + q log n),n 是字符串长度,q 是查询数量。
· 滑动窗口 O(n)
· 预处理前缀和 O(n)
· 每个查询二分查找 O(log n)
· 空间复杂度:O(n),存储 maxRight 和 preSum。

示例验证

```java
// 示例
String s = "000111";
int k = 1;
int[][] queries = {{0, 5}};
// 输出: [10]
// 解释: 满足 K 约束的子串有:
// "0","0","0","1","1","1","00","01","10","11" 等共10个
```

这个解法利用了滑动窗口的单调性和前缀和,在 LeetCode 上可以通过所有测试。

http://www.jsqmd.com/news/1020034/

相关文章:

  • 开源浏览器资源嗅探技术深度解析:猫抓扩展的架构设计与应用实践
  • 2026年 马鞍山颗粒板厂家推荐榜单:ENF实木颗粒板/防潮双饰面颗粒板,全屋定制优选品牌深度解析 - 品牌发掘
  • 2026年中山专利申请与无效律师推荐指南:从灯饰到五金全覆盖(中山企业收藏版) - 本地品牌推荐
  • Windows上安装APK的终极解决方案:告别模拟器,3分钟搞定安卓应用
  • 内证观察笔记
  • HsMod:炉石传说55项功能全能插件,彻底改变你的游戏体验 [特殊字符]
  • // SPDX-License-Identifier: GPL-2.0 九章编程矩阵化 bio 子系统 · 物理极限版 (~450 行) 屎山代码老系统,有人用,没人管
  • RAG大揭秘:8种架构解锁AI知识库新玩法,轻松提升大模型能力!
  • 太仓市高新技术企业认定的所需材料及申报流程
  • 【Java基础】堆与优先级的艺术:从急诊分诊到Top-K,手写一个PriorityQueue
  • 【电力系统】含氢气氨气综合能源系统优化调度研究附Matlab代码
  • 免费M3U8视频下载器终极指南:告别复杂命令行,一键下载在线视频
  • Anthropic会话抽象层(SAL)静默归零:客户端状态管理新范式
  • 华岐|正大|友发|振鸿|镀锌方管批发|四川盛世钢联国际贸易有限公司 - 四川盛世钢联营销中心
  • 3分钟快速上手:免费网页版PPTist在线演示文稿制作完全指南
  • 基于ZigBee RF4CE的无线HID设备开发:Freescale ZID应用配置详解
  • 2026年南宁配眼镜服务哪家更专业?实测8家眼镜店验光、镜片与售后服务体验 - 优质品牌商家
  • 深入解析NXP PXD10微控制器:显示控制、内存架构与系统设计实践
  • 2026年更新:泗洪无人机培训推荐指南与深度剖析 - 品牌鉴赏官2026
  • 九章编程法,抄同行的作业,加自己的功能,抄作业神器
  • 2026年 风机消音器/蒸汽消音器/排汽消音器/锅炉消音器厂家推荐:小孔与管道消音技术硬核解析 - 品牌发掘
  • 第35章:自定义 LLM、Embedding 与向量存储适配器
  • 用OpenAI API密钥构建可验证的深度研究工作流
  • 江苏省各市中国专利奖奖补政策是怎样的?
  • 别再被Prometheus日志里的‘无序时间戳’和‘重复样本’搞懵了,手把手教你定位和修复
  • 深度解析 Hermes 工具:本地 Agent 极简部署实操全流程
  • 包头高口碑黄金铂金回收白银回收实体老店排行 5 家靠谱门店电话地址全收录
  • 2026年6月口碑好的衡水装修公司找哪家推荐,全屋整装/毛坯装修/旧房翻新公司选择指南 - 海棠依旧大
  • 5步掌握KS-Downloader:终极快手无水印视频批量下载神器
  • 2026年武汉奢侈品回收市场深度调查:五家诚信商家全景评测与避坑指南 - 钦扬网络