力扣top100(day04-05)--堆

本文为力扣TOP100刷题笔记

笔者根据数据结构理论加上最近刷题整理了一套 数据结构理论加常用方法以下为该文章:

力扣外传之数据结构(一篇文章搞定数据结构)

215. 数组中的第K个最大元素

class Solution {// 快速选择递归函数int quickselect(int[] nums, int l, int r, int k) {if (l == r) return nums[k];  // 基准情况:区间只有一个元素// 选取基准值(这里简单选择最左边的元素)int x = nums[l], i = l - 1, j = r + 1;// 分区操作while (i < j) {// 从左找第一个大于等于x的元素do i++; while (nums[i] < x);// 从右找第一个小于等于x的元素do j--; while (nums[j] > x);// 交换这两个元素if (i < j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}}// 递归处理包含第k元素的子区间if (k <= j) return quickselect(nums, l, j, k);else return quickselect(nums, j + 1, r, k);}public int findKthLargest(int[] _nums, int k) {int n = _nums.length;// 将问题转化为找第n-k小的元素(即第k大的元素)return quickselect(_nums, 0, n - 1, n - k);}
}

算法步骤

  1. 分区(Partition)

    • 选择一个基准值(pivot)x(这里选择最左边的元素nums[l]

    • 使用两个指针ij

      • i从左向右找第一个≥x的元素

      • j从右向左找第一个≤x的元素

      • 交换这两个元素,直到ij相遇

  2. 递归选择

    • 根据k的位置决定递归处理左半部分还是右半部分

    • 如果k在左半部分(k <= j),继续处理左半部分

    • 否则处理右半部分

  3. 转换问题

    • 第k大的元素 = 第(n-k)小的元素(n - k

示例演示

假设输入数组为[3,2,1,5,6,4]k = 2(找第2大的元素):

  1. n = 6,转换为找第4小的元素(n - k = 4

  2. 初始调用quickselect(nums, 0, 5, 4)

  3. 分区过程:

    • 基准值x = 3

    • i找到5,j找到1

    • 交换后数组变为[3,2,1,4,6,5]

    • j停在索引2

  4. 因为4 > 2,递归处理右半部分quickselect(nums, 3, 5, 4)

  5. 再次分区:

    • 基准值x = 4

    • i找到6,j找到4

    • 交换后数组不变

    • j停在索引3

  6. 因为4 == 3,递归处理左半部分quickselect(nums, 3, 3, 4)

  7. 直接返回nums[4] = 5

最终结果是5,即第2大的元素。

时间复杂度

  • 平均情况:O(n)

  • 最坏情况(每次选择的基准值都是最大或最小值):O(n²)

347. 前 K 个高频元素

class Solution {public int[] topKFrequent(int[] nums, int k) {// 1. 使用哈希表统计每个数字出现的频率Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();for (int num : nums) {occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);}// 2. 创建最小堆,按照出现频率排序PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {public int compare(int[] m, int[] n) {return m[1] - n[1]; // 根据频率比较}});// 3. 遍历频率哈希表,维护大小为k的最小堆for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {int num = entry.getKey(), count = entry.getValue();if (queue.size() == k) {// 如果当前元素的频率大于堆顶元素的频率if (queue.peek()[1] < count) {queue.poll(); // 移除堆顶最小频率元素queue.offer(new int[]{num, count}); // 加入当前元素}} else {queue.offer(new int[]{num, count});}}// 4. 从堆中提取结果int[] ret = new int[k];for (int i = 0; i < k; ++i) {ret[i] = queue.poll()[0]; // 取出数字部分}return ret;}
}

算法步骤

  1. 统计频率

    • 使用哈希表occurrences记录每个数字出现的次数

    • 遍历数组,对每个数字的计数加1

  2. 构建最小堆

    • 创建优先队列(最小堆),比较器基于频率(数组的第二个元素)

    • 堆的大小限制为k,保持堆顶是当前k个元素中频率最小的

  3. 维护堆

    • 遍历频率哈希表

    • 当堆未满时,直接加入元素

    • 当堆已满时,比较当前元素频率与堆顶频率

      • 如果当前频率更高,替换堆顶元素

      • 否则跳过

  4. 提取结果

    • 从堆中依次取出元素,存入结果数组

    • 注意:由于是最小堆,取出的顺序是从小到大,但不影响结果正确性

示例演示

假设输入nums = [1,1,1,2,2,3]k = 2

  1. 统计频率:

    • occurrences = {1:3, 2:2, 3:1}

  2. 构建堆过程:

    • 加入1:3 → [(1,3)]

    • 加入2:2 → [(2,2), (1,3)]

    • 处理3:1时堆已满,3的频率1小于堆顶2的频率2,跳过

  3. 提取结果:

    • 弹出(2,2)和(1,3)

    • 结果[2,1](顺序不重要)

时间复杂度分析

  • 统计频率:O(n),n为数组长度

  • 建堆操作:O(m log k),m为不同数字的个数

    • 每个元素最多入堆一次,出堆一次

    • 堆操作时间复杂度为O(log k)

  • 总时间复杂度:O(n + m log k)

空间复杂度

  • 哈希表:O(m)

  • 堆:O(k)

  • 总空间复杂度:O(m + k)

优化建议

  1. 当k接近m时

    • 可以直接排序频率哈希表,取前k个

    • 时间复杂度O(m log m)

  2. 使用快速选择

    • 类似快速排序的分区思想

    • 平均时间复杂度O(n),但实现更复杂

  3. 并行处理

    • 对于大规模数据,可以并行统计频率

为什么使用最小堆?

最小堆能高效维护前k大的元素:

  1. 堆的大小限制为k,空间效率高

  2. 每次只需要比较堆顶元素,决定是否替换

  3. 插入和删除操作时间复杂度为O(log k)

这个实现很好地平衡了时间效率和代码简洁性,是解决Top K频率问题的经典方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93222.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CCS双轴相位偏移光源 让浅凹痕无处遁形

在工业检测中&#xff0c;浅凹痕表面检测对精度和可靠性要求极高&#xff0c;工业光源在此过程中扮演着关键角色&#xff0c;工业光源通过精准的光学设计&#xff08;角度、波长、强度&#xff09;将肉眼不可见的浅凹痕转化为可量化的光学信号&#xff0c;是实现高精度自动化检…

专题三_二分_x 的平方根

一&#xff1a;题目解释&#xff1a;返回x的算数平方根&#xff0c;如果是小数&#xff0c;则舍去小数部分&#xff0c;返回整数即可&#xff01;二&#xff1a;算法①&#xff1a;暴力从1开始求平方&#xff0c;最后要么直接找到一个值的平方为x&#xff0c;要么发现x在两个相…

Python 操作 Redis 的客户端库 redis-py

Python 操作 Redis 的客户端库 redis-py1. Installation2. Connect and test3. Connection Pools4. Redis Commands4.1. set(name, value, exNone, pxNone, nxFalse, xxFalse, keepttlFalse, getFalse, exatNone, pxatNone)4.1.1. setnx(name, value)4.1.2. setex(name, time, …

社区物业HCommunity本地部署手册

HC小区管理系统安装手动版 更多文章参考&#xff1a; http://www.homecommunity.cn/pages/hc/hcH5_cn.html 1.0 说明 很多开发不太喜欢用梓豪安装&#xff0c;希望通过手工自己安装&#xff0c;这个就需要开发人员 有一定的安装软件能力&#xff0c;比如能够自行安装mysql能…

单例模式-使用局部变量懒汉不用加锁

在 C11 及之后&#xff0c;“局部静态变量懒汉”&#xff08;Meyers’ Singleton&#xff09;不需要自己加锁&#xff0c;标准已经帮你做好了线程安全。 Singleton& getInstance() {static Singleton inst; // ← 这一句并发时只会初始化一次return inst; }首次调用时&am…

51单片机-GPIO介绍

本章概述思维导图&#xff1a;51单片机引脚介绍STC89系列51单片机引脚介绍STC89系列51单片机的引脚是单片机与外部电路连接的接口&#xff0c;用于实现电源供电、时钟信号输入、控制信号输出以及数据输入输出等功能。PDIP封装引脚图&#xff1a;1. 电源引脚&#xff1a;VCC&…

CERT/CC警告:新型HTTP/2漏洞“MadeYouReset“恐致全球服务器遭DDoS攻击瘫痪

2025年8月15日CERT/CC&#xff08;计算机应急响应协调中心&#xff09;近日发布漏洞公告&#xff0c;警告多个HTTP/2实现中新发现的缺陷可能被威胁行为者用于发起高效拒绝服务&#xff08;DoS&#xff09;或分布式拒绝服务&#xff08;DDoS&#xff09;攻击。该漏洞被非正式命名…

[Chat-LangChain] 会话图(LangGraph) | 大语言模型(LLM)

第二章&#xff1a;会话图&#xff08;LangGraph&#xff09; 在第一章中&#xff0c;我们学习了前端用户界面——这是聊天机器人的"面孔"&#xff0c;我们在这里输入问题并查看答案。 我们看到了消息如何从聊天窗口传递到聊天机器人的"大脑"。现在&…

Flask错误处理与会话技术详解

flask入门day03 错误处理 1.abort函数&#xff1a;放弃请求并返回错误代码 详细状态码 from flask import Flask,abort,render_template ​ app Flask(__name__) ​ app.route(/) def index():return 我是首页 ​ app.route(/error) def error():abort(404)return 没有找到…

java程序打包成exe,再打成安装包,没有jdk环境下可运行

一、前提条件准备&#xff1a;1、要被打包的程序文件&#xff1a;rest_assistant-1.0-SNAPSHOT.jarapplication.yml2、图标文件tubiao123.ico3、jre4、打包成exe的软件 config.exe4j5、打成安装包的软件 Inno Setup Compiler二、config.exe4j 的 exe打包配置步骤 按照以下图进行…

区块链技术原理(11)-以太坊交易

文章目录什么是交易&#xff1f;交易类型交易生命周期关键概念&#xff1a;Gas 与交易费用交易状态与失败原因总结什么是交易&#xff1f; “交易&#xff08;Transaction&#xff09;” 是从一个账户向另一个账户发送的经过数字签名的指令 。例如&#xff0c;如果 Bob 发送 A…

小兔鲜儿-小程序uni-app(二)

小兔鲜儿-小程序uni-app7.小兔鲜儿 - 用户模块会员中心页(我的)静态结构参考代码会员设置页分包预下载静态结构退出登录会员信息页静态结构获取会员信息渲染会员信息更新会员头像更新表单信息8.小兔鲜儿 - 地址模块准备工作静态结构地址管理页地址表单页动态设置标题新建地址页…

BLE 广播信道与数据信道:冲突避免、信道映射与自适应跳频实现

低功耗蓝牙(BLE)技术凭借低功耗、短距离、低成本的特性,已广泛应用于智能家居、可穿戴设备、工业物联网等领域。在 BLE 协议中,信道管理是保障通信可靠性的核心机制,其中广播信道与数据信道的设计、冲突避免策略、跳频技术更是面试中的高频考点。本文将从基础原理到实战真…

nodejs03-常用模块

nodejs 常用的核心模块 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c; 它允许 JavaScript 运行在服务器端。Node.js 拥有丰富的标准库&#xff0c;也就是核心模块&#xff0c; 这些模块提供了各种功能&#xff0c; 使得开发服务器端应用程序变得简单高…

多路混音声音播放芯片型号推荐

以下是唯创知音旗下主流的多路声音播放芯片深度解析&#xff0c;结合精准参数、丰富场景及技术特性&#xff0c;满足智能设备多样化音频需求&#xff1a;一、WTV380/890 系列&#xff1a;高集成多模态交互芯片核心参数通道能力&#xff1a;支持8 路独立语音输出&#xff0c;可同…

【C++】自研基 2 Cooley–Tukey

“自研基 2 Cooley–Tukey&#xff1a;倒位序 逐级蝶形&#xff0c;入口 fft(int N, complex f[])”拆成三件事它在讲什么 “基 2 Cooley–Tukey” 指的是最常见的 FFT 算法&#xff1a;长度 N 必须是 2 的整数次幂&#xff0c;把离散傅里叶变换分解成一层一层的“2 点蝶形”运…

小白挑战一周上架元服务——ArkUI04

文章目录前言一、ArkUI是何方神圣&#xff1f;二、声明式UI三、组件1.基础组件2.布局容器组件3.导航组件4.自定义组件5.组件生命周期四、状态管理1.State装饰器: 状态变量2.Prop装饰器&#xff1a;父子单向同步3.Link装饰器&#xff1a;父子双向同步4.Provide/Consume装饰器&am…

剧本杀小程序系统开发:构建剧本杀社交新生态

在社交需求日益多样化的今天&#xff0c;剧本杀凭借其独特的社交属性&#xff0c;成为了人们热衷的社交娱乐方式之一。而剧本杀小程序系统开发&#xff0c;则进一步拓展了剧本杀的社交边界&#xff0c;构建起一个全新的剧本杀社交新生态&#xff0c;让玩家在推理与角色扮演中&a…

AI提高投放效率的核心策略

内容概要人工智能技术正深刻改变着广告投放领域&#xff0c;其核心价值在于显著提升投放效率。通过融合智能算法优化、实时数据分析与自动化投放流程&#xff0c;AI系统能够以前所未有的速度和精度处理海量信息&#xff0c;驱动更精准的营销决策。这不仅大幅缩短了传统人工操作…

OpenBMC 中命令模式的深度解析:从原理到实现

引言 在 OpenBMC 的设计中&#xff0c;命令模式&#xff08;Command Pattern&#xff09;被广泛应用于各种场景&#xff0c;特别是 IPMI 命令处理、异步操作封装和用户请求管理等。本文将深入分析 OpenBMC 中命令模式的实现原理、架构设计以及完整的执行流程&#xff0c;并通过…