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

豆包 LeetCode 3134. 找出唯一性数组的中位数 Java实现

LeetCode 3134. 找出唯一性数组的中位数 Java 实现

题目简析

题意
给定数组 nums ,生成其所有子数组,对每个子数组计算不同元素的个数,得到「唯一性数组」。求该数组的中位数。

关键点:

1. 子数组总数:n = nums.length,子数组总个数 total = \dfrac{n(n+1)}{2}
2. 中位数位置:若数组长度为 m,中位数是第 \lceil m/2 \rceil 小的数(1-index)
3. 核心思路:二分答案 + 滑动窗口(统计不同元素个数 \le mid 的子数组数量)



解题思路

1. 二分值域:唯一性取值范围是 [1, n],二分枚举答案 k。
2. 滑动窗口计数:用双指针统计「不同元素数量 \le k」的子数组总数 cnt 。
3. 二分判定:
- 若 cnt >= 中位数位次 :说明答案在左半区间,收缩右边界
- 否则:答案在右半区间,收缩左边界



Java 完整代码

java
import java.util.HashMap;
import java.util.Map;

public class Solution {
public int medianOfUniquenessArray(int[] nums) {
int n = nums.length;
// 所有子数组总数
long total = (long) n * (n + 1) / 2;
// 中位数是第 pos 小(1-index)
long pos = (total + 1) / 2;

int left = 1, right = n;
while (left < right) {
int mid = left + (right - left) / 2;
long count = countSubarray(nums, mid);
if (count >= pos) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}

// 统计:不同元素个数 <= k 的子数组数量
private long countSubarray(int[] nums, int k) {
Map<Integer, Integer> freq = new HashMap<>();
int l = 0;
long res = 0;
for (int r = 0; r < nums.length; r++) {
int cur = nums[r];
freq.put(cur, freq.getOrDefault(cur, 0) + 1);

// 不同元素超过 k,左指针右移
while (freq.size() > k) {
int leftVal = nums[l];
freq.put(leftVal, freq.get(leftVal) - 1);
if (freq.get(leftVal) == 0) {
freq.remove(leftVal);
}
l++;
}
// 以 r 为右端点的合法子数组数量:r - l + 1
res += r - l + 1;
}
return res;
}
}




复杂度分析

- 时间复杂度:O(n \log n)
二分次数:O(\log n),每次滑动窗口遍历数组:O(n)
- 空间复杂度:O(n),哈希表存储元素频次



补充说明

1. 数据类型注意
子数组总数会达到 \dfrac{n(n+1)}{2},n 最大可取 10^5,结果会溢出 int ,必须用 long 存计数、位次。
2. 中位数位置推导
举例:
- m=5:位次 (5+1)/2=3,第 3 小
- m=4:位次 (4+1)/2=2(整数除法),第 2 小
符合题目中位数定义。
3. 滑动窗口逻辑
固定右端点 r ,找到最小左端点 l ,区间 [l,r] 内不同元素 \le k。
以 r 结尾的合法子数组数量 = r-l+1,累加即可。



优化(数组替代 HashMap,提速)

若元素值域不大,可用数组替代哈希表,进一步提速:

java
public class Solution {
static final int MAX = (int) 1e6 + 10;
int[] freq = new int[MAX];

public int medianOfUniquenessArray(int[] nums) {
int n = nums.length;
long total = (long) n * (n + 1) / 2;
long pos = (total + 1) / 2;

int left = 1, right = n;
while (left < right) {
int mid = left + (right - left) / 2;
long count = countSubarray(nums, mid);
if (count >= pos) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}

private long countSubarray(int[] nums, int k) {
// 重置频次数组
java.util.Arrays.fill(freq, 0);
int l = 0, diff = 0;
long res = 0;
for (int r = 0; r < nums.length; r++) {
int cur = nums[r];
if (freq[cur] == 0) diff++;
freq[cur]++;

while (diff > k) {
int leftVal = nums[l];
freq[leftVal]--;
if (freq[leftVal] == 0) diff--;
l++;
}
res += r - l + 1;
}
return res;
}
}


该版本在大数据用例下运行更快,适合题目数据范围。

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

相关文章:

  • 从零搭建 OpenClaw 详解权限拦截、中文路径等问题处理方案
  • 2026乐山临江鳝丝实测指南:哪家店值得专程打卡?非遗技艺与市井烟火的终极对决 - 优质品牌商家
  • NeuroSymActive框架:神经符号推理与主动学习的融合实践
  • 2026年草种厂家直供品牌怎么选?从运动场到高原修复的实战解析 - 优质品牌商家
  • 2026年重庆高中学校怎么选?|基于升学路径、师资配置与教学管理的客观分析 - 优质品牌商家
  • 生产级模型部署全链路指南:从Flask到云原生MLOps
  • Markdown 完全指南:从入门到精通
  • 生产级多维聚合:一次groupby搞定可解释、可落地的分析口径
  • 成都企云讯灵 geo 口碑怎么样? - 工业推荐榜
  • 2026年银川合同律师哪家好?5位实战经验丰富值得信赖推荐 - 本地品牌推荐
  • 老旧小区物业团购模式的数智化技术落地实践
  • 码上云启:华为云码道双 Skill 一键部署云资源 Web 服务
  • 2026下半年墙面手绘墙画涂鸦品牌怎么选?多家主体案例与市场趋势分析 - 优质品牌商家
  • R语言中ANOVA与ANCOVA实战:从方差分解到协变量校准
  • 2026年饮用水管道防腐涂料怎么选?口碑推荐与多品牌横向评测 - 优质品牌商家
  • VideoDownloadHelper:Chrome视频下载插件终极使用指南
  • 机器学习算法选择决策框架:从问题诊断到落地适配
  • 2026年POREX管式膜定制厂家十大排名,哪家靠谱? - 工业推荐榜
  • 2026年成都国际国内货物运输代理服务格局观察:本土企业的差异化竞争力与行业趋势 - 优质品牌商家
  • 【OrCAD】【TCL】【获取连接器引脚信息】
  • Python 高手编程系列三千三百九十八:非确定性缓存
  • 2026年成都办公室打印机租赁公司怎么选?四家服务商横向对比分析 - 优质品牌商家
  • C# WinForms项目直接调用C++开发的OCX控件实操包(含注册配置与调试工程)
  • MuleSoft+LLM企业级AI编排:安全可控的智能工作流实践
  • 基于深度学习YOLOv12的PCB印刷版元器件识别检测系统(YOLOv12+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • Linux 10 防火墙
  • 第三:selenium中iframe和下拉框操作
  • 憨大叔旅游社选购注意什么 - 工业推荐榜
  • FastAPI构建ML-Ready API:特征校验与模型版本管理实战
  • Langflow 高危漏洞 CVE-2026-5027 已遭野外利用:未修补的路径遍历可致远程代码执行