当前位置: 首页 > 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.zskr.cn/news/1508524.html

相关文章:

  • NeuroSymActive框架:神经符号推理与主动学习的融合实践
  • 2026年重庆高中学校怎么选?|基于升学路径、师资配置与教学管理的客观分析 - 优质品牌商家
  • 码上云启:华为云码道双 Skill 一键部署云资源 Web 服务
  • 2026年饮用水管道防腐涂料怎么选?口碑推荐与多品牌横向评测 - 优质品牌商家
  • 第三:selenium中iframe和下拉框操作
  • Langflow 高危漏洞 CVE-2026-5027 已遭野外利用:未修补的路径遍历可致远程代码执行
  • 2026年医疗变压器与稳压电源行业深度观察:哪些厂商在技术、服务与案例上更具竞争力? - 优质品牌商家
  • Hackintool终极指南:5步解决黑苹果配置难题的完整教程
  • 免费开源3D建模革命:用Meshroom从照片创建专业级三维模型的终极指南
  • ComfyUI-Impact-Pack V8架构深度解析:模块化设计如何重塑AI图像处理工作流
  • 2026年兰州装饰公司怎么选?本地装修公司、工作室与设计机构深度行业分析 - 优质品牌商家
  • 2026年靠谱的外墙保温/烟台外墙保温/烟台外墙保温隔热值得信赖公司 - 行业平台推荐
  • AI自省机制:让大模型实时感知并熔断幻觉输出
  • GitHub年度回顾工具:用数据叙事重构开发者体验
  • LangChain+Weaviate+Streamlit构建企业级法律问答机器人
  • 微信读书笔记助手WeReader:一键导出高效笔记的完整解决方案
  • 2026年成都废旧物资回收公司怎么选?多维度实测与行业趋势分析 - 优质品牌商家
  • 第四:窗口标签页切换和元素等待
  • p-Tau217 :解锁神经退行性疾病早期诊断的关键钥匙
  • 深度学习图像质量评估终极指南:3步让计算机看懂好照片
  • 2026年知名的上海高级感发型设计/上海发型设计/根据脸型发型设计哪家效果好 - 品牌宣传支持者
  • 2026年口碑好的乌尔禾区烤全羊/克拉玛依乌尔禾区大盘鸡/克拉玛依乌尔禾区新疆菜口碑推荐 - 行业平台推荐
  • ros2-quick-runner插件v0.0.4版本发布
  • 做游戏缺背景音乐?12个优质可商用素材站点整理
  • ComfyUI-WanVideoWrapper:突破性AI视频生成框架的深度技术解析
  • 2026年评价高的乌尔禾区大盘鸡/乌尔禾区新疆菜/克拉玛依乌尔禾区大盘鸡/克拉玛依乌尔禾区新疆菜好吃推荐 - 品牌宣传支持者
  • 采购、生产、质检三类部门,制造业Agent选型标准为什么完全不同?
  • 伪Anosov流与双曲几何中的边界不可压缩曲面研究
  • 如何用Vue Json Pretty组件优雅展示JSON数据:完整指南
  • 终极指南:如何快速解密微信聊天记录实现本地数据备份