Kimi LeetCode 3569. 分割数组后不同质数的最大数目 JavaScript实现

发布时间:2026/7/25 1:35:41
Kimi    LeetCode 3569. 分割数组后不同质数的最大数目 JavaScript实现
以下是 LeetCode 3569「分割数组后不同质数的最大数目」的 JavaScript 实现。核心思路将数组在位置 k1 ≤ k n处分割为左右两部分。对于某个质数 p- 若 p 在数组中只出现 1 次无论怎么分割它只能出现在一边贡献 1。- 若 p 出现 ≥ 2 次首次在 l末次在 r- 当分割点 k ∈ [l1, r] 时p 会同时出现在左右两边贡献 2额外贡献 1。- 否则贡献 1。因此每次查询的答案为 不同质数的总数 最大额外贡献其中「最大额外贡献」等价于在区间 [1, n-1] 中有多少个质数满足 k ∈ [l1, r]。这需要用懒标记线段树维护区间加、区间最大值以支持 O(log n) 的单点修改。代码实现javascript/*** param {number[]} nums* param {number[][]} queries* return {number[]}*/var maximumCount function(nums, queries) {const MX 100000;const n nums.length;// 筛法预处理质数const isPrime new Array(MX 1).fill(true);isPrime[0] isPrime[1] false;for (let i 2; i * i MX; i) {if (isPrime[i]) {for (let j i * i; j MX; j i) {isPrime[j] false;}}}// 懒标记线段树区间加、区间最大值class LazySegTree {constructor(size, initVal) {this.n size;this.mx new Array(4 * size).fill(0);this.lazy new Array(4 * size).fill(0);this._build(1, 0, size - 1, initVal);}_build(node, l, r, initVal) {if (l r) {this.mx[node] initVal;return;}const mid (l r) 1;this._build(node 1, l, mid, initVal);this._build(node 1 | 1, mid 1, r, initVal);this.mx[node] Math.max(this.mx[node 1], this.mx[node 1 | 1]);}_apply(node, val) {this.mx[node] val;this.lazy[node] val;}_push(node) {const val this.lazy[node];if (val ! 0) {this._apply(node 1, val);this._apply(node 1 | 1, val);this.lazy[node] 0;}}_update(node, l, r, ql, qr, val) {if (ql l r qr) {this._apply(node, val);return;}this._push(node);const mid (l r) 1;if (ql mid) this._update(node 1, l, mid, ql, qr, val);if (qr mid) this._update(node 1 | 1, mid 1, r, ql, qr, val);this.mx[node] Math.max(this.mx[node 1], this.mx[node 1 | 1]);}update(l, r, val) {if (l r) return;this._update(1, 0, this.n - 1, l, r, val);}query() {return this.mx[1];}}// pos[p] 质数 p 的所有出现位置有序数组const pos new Map();for (let i 0; i n; i) {const x nums[i];if (isPrime[x]) {if (!pos.has(x)) pos.set(x, []);pos.get(x).push(i);}}// 初始化线段树对出现 ≥ 2 次的质数在 [l1, r] 区间 1const seg new LazySegTree(n, 0);for (const arr of pos.values()) {if (arr.length 2) {const l arr[0];const r arr[arr.length - 1];const left Math.max(l 1, 1);const right Math.min(r, n - 1);if (left right) seg.update(left, right, 1);}}const ans [];// 从质数 p 的位置数组中删除索引 idxfunction removeFromPrime(p, idx) {const arr pos.get(p);const len arr.length;if (len 1) {pos.delete(p);return;}const l arr[0];const r arr[len - 1];let posIdx -1;for (let i 0; i len; i) {if (arr[i] idx) { posIdx i; break; }}if (posIdx -1) return;arr.splice(posIdx, 1);if (len 2) {// 从 2 个变 1 个消除该质数的额外贡献const left Math.max(l 1, 1);const right Math.min(r, n - 1);if (left right) seg.update(left, right, -1);} else {const newL arr[0];const newR arr[arr.length - 1];if (idx l) {// 删除了最左端范围从左边收缩const left Math.max(l 1, 1);const right Math.min(newL, n - 1);if (left right) seg.update(left, right, -1);} else if (idx r) {// 删除了最右端范围从右边收缩const left Math.max(newR 1, 1);const right Math.min(r, n - 1);if (left right) seg.update(left, right, -1);}// 若删除的是中间位置[l, r] 不变无需更新}}// 向质数 p 的位置数组中添加索引 idxfunction addToPrime(p, idx) {if (!pos.has(p)) {pos.set(p, [idx]);return;}const arr pos.get(p);const len arr.length;const l arr[0];const r arr[len - 1];let insertPos 0;while (insertPos len arr[insertPos] idx) insertPos;arr.splice(insertPos, 0, idx);if (len 1) {// 从 1 个变 2 个新增额外贡献const newL arr[0];const newR arr[1];const left Math.max(newL 1, 1);const right Math.min(newR, n - 1);if (left right) seg.update(left, right, 1);} else {const newL arr[0];const newR arr[arr.length - 1];if (idx l) {// 向左扩展const left Math.max(idx 1, 1);const right Math.min(l, n - 1);if (left right) seg.update(left, right, 1);} else if (idx r) {// 向右扩展const left Math.max(r 1, 1);const right Math.min(idx, n - 1);if (left right) seg.update(left, right, 1);}// 若插入到中间[l, r] 不变无需更新}}// 处理每个查询for (const q of queries) {const idx q[0];const val q[1];const old nums[idx];nums[idx] val;if (isPrime[old]) removeFromPrime(old, idx);if (isPrime[val]) addToPrime(val, idx);ans.push(pos.size seg.query());}return ans;};复杂度分析- 时间复杂度O((n q) · log n)其中 q 为查询次数。每次单点修改涉及线段树的 O(log n) 更新。- 空间复杂度O(n)用于线段树、筛法数组和质数位置映射。

相关新闻

最新新闻

5步精通Windows DLL注入:Xenos注入器深度实战指南

5步精通Windows DLL注入:Xenos注入器深度实战指南

5步精通Windows DLL注入:Xenos注入器深度实战指南 【免费下载链接】Xenos Windows dll injector 项目地址: https://gitcode.com/gh_mirrors/xe/Xenos 在Windows系统开发与安全研究领域,DLL注入技术一直是连接进程隔离壁垒的关键桥梁。你是否曾面…

2026/7/25 18:09:15
AI编舞技术解析:从文本描述到舞蹈动作生成的完整实践指南

AI编舞技术解析:从文本描述到舞蹈动作生成的完整实践指南

最近在AI生成领域,一个名为"haru moe 编舞FLO - Wolk Like This"的项目引起了广泛关注。这个看似简单的标题背后,实际上代表了AI在创意内容生成领域的一个重要突破——将文本描述转化为高质量的舞蹈动作序列。 对于开发者而言,这类…

2026/7/25 8:11:28
无人机继电器原理与实战:从APM1到Pixhawk的物理控制方案

无人机继电器原理与实战:从APM1到Pixhawk的物理控制方案

1. 项目概述:为什么无人机上需要一个“机械手”来按开关? 在 Pixhawk 生态里,尤其是早期基于 APM 1/2 硬件平台的飞控系统中,“继电器开关(Relay Switch)”这个功能模块,常被新手误认为是“可有…

2026/7/25 14:54:19
C++构建电商实时画像系统:高并发架构与性能优化实战

C++构建电商实时画像系统:高并发架构与性能优化实战

1. 项目概述:为什么用C做电商画像系统? 当大家聊起电商大数据画像系统,第一反应往往是Java、Python或者Scala,毕竟Hadoop、Spark这些生态圈的主流语言摆在那里。但今天我想分享一个基于C构建的实战项目,这听起来可能有…

2026/7/25 14:59:52
convoC2未来路线图:消息加密、心跳检测与PowerShell版本开发计划

convoC2未来路线图:消息加密、心跳检测与PowerShell版本开发计划

convoC2未来路线图:消息加密、心跳检测与PowerShell版本开发计划 【免费下载链接】convoC2 C2 infrastructure over Microsoft Teams. 项目地址: https://gitcode.com/gh_mirrors/co/convoC2 convoC2作为基于Microsoft Teams的C2基础设施项目,正…

2026/7/25 14:14:54
【滤波跟踪】基于扩展卡尔曼滤波器 (EKF) 实现 UAV-UGV 系统的协作定位附Matlab代码

【滤波跟踪】基于扩展卡尔曼滤波器 (EKF) 实现 UAV-UGV 系统的协作定位附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/7/25 14:50:47

日新闻

周新闻

月新闻