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

【中等】出现次数的TOPK问题-Java:原问题

分享一个大牛的人工智能教程。零基础通俗易懂风趣幽默希望你也加入到人工智能的队伍中来请轻击人工智能教程大家好欢迎来到我的网站 人工智能被认为是一种拯救世界、终结世界的技术。毋庸置疑人工智能时代就要来临了科… 继续阅读 前言https://www.captainai.net/troubleshooterpackage live.every.day.ProgrammingDesign.CodingInterviewGuide.Other; import java.util.HashMap; import java.util.Map; /** * 出现次数的TOPK问题 * * 【题目】 * 给定String类型的数组strArr再给定整数k请严格按照排名顺序打印出现次数前k名的字符串。 * * 【举例】 * strArr[1,2,3,4]k2 * No.1: 1, times: 1 * No.2: 2, times: 1 * 这种情况下所有的字符串都出现一样多随便打印任何两个字符串都可以。 * * strArr[1,1,2,3]k2 * 输出 * No.1: 1, times: 2 * No.2: 2, times: 1 * 或者输出 * No.1: 1, times: 2 * No.2: 3, times: 1 * * 【要求】 * 如果strArr长度为N时间复杂度请达到O(Nlogk)。 * * 【进阶题目】 * 设计并实现TopKRecord结构可以不断地向其中加入字符串并且可以根据字符串出现的情况随时打印加入次数最多前k个字符串 * 具体为 * 1.k在TopKRecord实例生成时指定并且不再变化(k是构造函数的参数)。 * 2.含有add(String str)方法即向TopKRecord中加入字符串。 * 3.含有printTopK()方法即打印加入次数最多的前k个字符串打印有哪些字符串和对应的次数即可不要求严格按排名顺序打印。 * * 【举例】 * TopKRecord record new TopKRecord(2); // 打印Top2的结构 * record.add(A); * record.printTopK(); * 此时打印 * TOP: * Str: A Times: 1 * * record.add(B): * record.add(B); * record.printTopK(); * 此时打印 * TOP: * Str: A Times: 1 * Str: B Times: 2 * 或者打印 * TOP: * Str: B Times: 2 * Str: A Times: 1 * * record.add(C); * record.add(C); * record.printTopK(); * 此时打印 * TOP: * Str: B Times: 2 * Str: C Times: 2 * 或者打印 * TOP: * Str: C Times: 2 * Str: B Times: 2 * * 【要求】 * 1.在任何时刻add方法的时问复杂度不超过O(logk)。 * 2.在任何时刻printTopK方法的时间复杂度不超过O(k)。 * * 【难度】 * 原问题中等 * 进阶问题困难 * * 【解答】 * 原问题。首先遍历strArr并统计字符串的词频例如strArr[a,b,bac]遍历后可以生成每种字符串及其相关 * 词频的哈希表如下。 * 用哈希表的每条信息可以生成Node类的实例Node类如下。 * 哈希表中有多少信息就建立多少Node类的实例并且依次放入堆中具体过程为 * 1.建立一个大小为k的小根堆这个堆放入的是Node类的实例。 * 2.遍历哈希表的每条记录假设一条记录为(s,t)s表示一种字符串s的词频为t则生成Node类的实例记为(str,times)。 * 1如果小根堆没有满就直按将(str,times)加入堆然后进行建堆调整(heapInsert调整)堆中Node类实例之间都以词频 * (times)来进行比较词频越小位置越往上。 * 2如果小根堆已满说明此时小根堆已经选出k个最高词频的字符串那么整个小根堆的堆顶自然代表已经选出的k个最高词频的字符 * 串中词频最低的那个。堆顶的元素记为(headStr,minTimes)。如果minTimestimes说明字符串str有资格进入当前k个最高 * 词频字符串的范围。而headStr应该被移出这个范围所以把当前的堆顶(headStr,minTimes)替换成(str,times)然后从堆顶 * 的位置进行堆的调整(heapify)。如果minTimestimes说明字符串str没有资格进入当前k个最高词频字符串的范围因为str * 的词频还不如目前选出的k个最高词频字符串中词频最少的那个所以什么也不做。 * 3.遍历完strArr之后小根堆里就是所有字符串中k个最高词频的字符串但要求严格按排名打印所以还需要根据词频从大到小完成 * k个元素间的排序。 * 遍历strArr建立哈希表的过程为O(N)。哈希表中记录的条数最多为N条每一条记录进堆时堆的调整时间复杂度为O(logk)所以 * 根据记录更新小根堆的过程为O(Nlogk)。k条记录排序的时间复杂度为O(klogk)。所以总的时间复杂度为 * O(N)O(Nlogk)O(klogk)即O(Nlogk)。 * 具体过程请参看如下代码中的printTopKAndRank方法。 * * author Created by LiveEveryDay */ public class AppearTimesTopKProblem1 { public static class Node { public String str; public int times; public Node(String s, int t) { str s; times t; } } public static void printTopKAndRank(String[] arr, int topK) { if (arr null || topK 1) { return; } HashMapString, Integer map new HashMap(); // 生成哈希表字符串词频 for (int i 0; i ! arr.length; i) { String cur arr[i]; if (!map.containsKey(cur)) { map.put(cur, 1); } else { map.put(cur, map.get(cur) 1); } } Node[] heap new Node[topK]; int index 0; // 遍历哈希表决定每条信息是否进堆 for (Map.EntryString, Integer entry : map.entrySet()) { String str entry.getKey(); int times entry.getValue(); Node node new Node(str, times); if (index ! topK) { heap[index] node; heapInsert(heap, index); } else { if (heap[0].times node.times) { heap[0] node; heapify(heap, 0, topK); } } } // 把小根堆的所有元素按词频从大到小排序 for (int i index - 1; i ! 0; i--) { swap(heap, 0, i); heapify(heap, 0, i); } // 严格按照排名打印k条记录 for (int i 0; i ! heap.length; i) { if (heap[i] null) { break; } else { System.out.print(No. (i 1) : ); System.out.print(heap[i].str , times: ); System.out.println(heap[i].times); } } } public static void heapInsert(Node[] heap, int index) { while (index ! 0) { int parent (index - 1) 1; if (heap[index].times heap[parent].times) { swap(heap, parent, index); index parent; } else { break; } } } public static void heapify(Node[] heap, int index, int heapSize) { int left index * 2 1; int right index * 2 2; int smallest index; while (left heapSize) { if (heap[left].times heap[index].times) { smallest left; } if (right heapSize heap[right].times heap[smallest].times) { smallest right; } if (smallest ! index) { swap(heap, smallest, index); } else { break; } index smallest; left index * 2 1; right index * 2 2; } } public static void swap(Node[] heap, int index1, int index2) { Node tmp heap[index1]; heap[index1] heap[index2]; heap[index2] tmp; } public static void main(String[] args) { String[] arr {C, D, D, E, E}; int topK 2; printTopKAndRank(arr, topK); } } // ------ Output ------ /* No.1: D, times: 2 No.2: E, times: 2 */

相关文章:

【中等】出现次数的TOPK问题-Java:原问题

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程大家好!欢迎来到我的网站! 人工智能被认为是一种拯救世界、终结世界的技术。毋庸置疑&#x…...

别再手动算频谱了!手把手教你用STM32CubeMX+DSP库搞定FFT(附源码避坑)

STM32CubeMXDSP库实战:5步搞定高精度FFT频谱分析 开发板上那个不起眼的ADC接口,可能正藏着解锁信号奥秘的钥匙。去年在智能家居声纹识别项目里,我们团队花了三周时间才调通第一个可用的频谱分析模块——不是因为算法复杂,而是掉进…...

机器学习必备:微积分核心概念与实战应用

1. 为什么机器学习从业者需要微积分基础 在机器学习领域,我们经常听到一个矛盾的说法:一方面很多实践者声称"不懂数学也能做机器学习",另一方面所有顶尖的机器学习教材都充斥着数学符号和推导。这种认知差异的核心在于,…...

AI加速器架构解析:从GPU到存内计算的技术演进

1. AI加速器的技术演进背景人工智能计算正面临前所未有的算力需求挑战。现代大型语言模型(LLM)的参数规模已经突破万亿级别,训练这样的模型需要数千块GPU连续工作数月,消耗数百万美元的计算资源。这种指数级增长的计算需求直接推动…...

为什么fastp比Trimmomatic快10倍?深度解析其核心算法原理

为什么fastp比Trimmomatic快10倍?深度解析其核心算法原理 【免费下载链接】fastp An ultra-fast all-in-one FASTQ preprocessor (QC/adapters/trimming/filtering/splitting/merging...) 项目地址: https://gitcode.com/gh_mirrors/fa/fastp 在高通量测序数…...

Labwc主题定制终极教程:如何让你的桌面焕然一新

Labwc主题定制终极教程:如何让你的桌面焕然一新 【免费下载链接】labwc A Wayland window-stacking compositor 项目地址: https://gitcode.com/gh_mirrors/la/labwc Labwc作为一款轻量级Wayland窗口堆叠管理器,不仅性能出色,还提供了…...

Mastodon iOS:官方开源社交应用完全解析与入门指南

Mastodon iOS:官方开源社交应用完全解析与入门指南 【免费下载链接】mastodon-ios Official iOS app for Mastodon 项目地址: https://gitcode.com/gh_mirrors/ma/mastodon-ios Mastodon iOS是官方推出的开源社交应用,为用户提供了一个去中心化的…...

卡方检验(Chi-Squared Test)在特征工程中的实战应用

1. 卡方检验在特征工程中的核心价值 第一次接触卡方检验时,我也被那些统计学术语搞得头晕。直到在真实项目中用它筛选出关键特征,才真正理解它的威力。简单来说,卡方检验就像个"相关性探测器",能帮我们快速找出那些对预…...

vue-json-schema-form表单联动实战:复杂业务场景的终极解决方案

vue-json-schema-form表单联动实战:复杂业务场景的终极解决方案 【免费下载链接】vue-json-schema-form 基于Vue/Vue3,Json Schema 和 ElementUi/antd/iview3/naiveUi 等生成 HTML Form 表单,用于活动编辑器、h5编辑器、cms等数据配置&#x…...

NextJS与ChatGPT构建智能职位描述生成器实践

1. 项目概述:用NextJS和ChatGPT打造智能职位描述生成器最近在帮HR朋友优化招聘流程时,发现编写职位描述(JD)是个高频且耗时的痛点。传统做法要么复制粘贴模板导致同质化严重,要么反复修改耗费数小时。于是我用NextJS框架结合ChatGPT API开发了…...

HAPI FHIR客户端开发完全指南:从基础调用到高级功能

HAPI FHIR客户端开发完全指南:从基础调用到高级功能 【免费下载链接】hapi-fhir 🔥 HAPI FHIR - Java API for HL7 FHIR Clients and Servers 项目地址: https://gitcode.com/gh_mirrors/ha/hapi-fhir HAPI FHIR是一个功能强大的Java API&#xf…...

SVGo性能优化:如何高效处理大规模SVG图形生成

SVGo性能优化:如何高效处理大规模SVG图形生成 【免费下载链接】svgo Go Language Library for SVG generation 项目地址: https://gitcode.com/gh_mirrors/svg/svgo SVGo是一个强大的Go语言SVG生成库,它允许开发者通过简洁的API创建复杂的矢量图形…...

LLM Compressor性能优化:如何选择最佳的压缩方案和硬件配置

LLM Compressor性能优化:如何选择最佳的压缩方案和硬件配置 【免费下载链接】llm-compressor Transformers-compatible library for applying various compression algorithms to LLMs for optimized deployment with vLLM 项目地址: https://gitcode.com/gh_mirr…...

Cortex MoE大模型快速入门:5分钟完成本地部署和在线体验

Cortex MoE大模型快速入门:5分钟完成本地部署和在线体验 【免费下载链接】Cortex 从零构建大模型:从预训练到RLHF的完整实践 项目地址: https://gitcode.com/gh_mirrors/cortex27/Cortex Cortex是一个从零构建大模型的开源项目,涵盖从…...

云环境LLC缓存争用检测与优化实践

1. 云虚拟机缓存争用问题概述在云计算环境中,多个虚拟机(VM)共享物理主机的最后一级缓存(LLC)是常态。这种资源共享机制虽然提高了硬件利用率,但也带来了严重的缓存争用问题。当多个虚拟机频繁访问LLC时&am…...

ComfyUI-Impact-Pack终极指南:三步解锁AI图像增强的完整功能

ComfyUI-Impact-Pack终极指南:三步解锁AI图像增强的完整功能 【免费下载链接】ComfyUI-Impact-Pack Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more. 项目地址: ht…...

10分钟上手PPTAgent:从文档到精美幻灯片的完整教程

10分钟上手PPTAgent:从文档到精美幻灯片的完整教程 【免费下载链接】PPTAgent An Agentic Framework for Reflective PowerPoint Generation 项目地址: https://gitcode.com/gh_mirrors/pp/PPTAgent PPTAgent是一款基于智能代理框架的幻灯片生成工具&#xf…...

Linux运维实战:命令行高效管理OSS对象存储

1. 为什么Linux运维需要掌握OSS命令行工具 作为Linux服务器运维工程师,每天都要处理海量数据备份、日志归档和资源分发。传统做法是用scp或rsync在服务器间来回传输,但很快就遇到存储空间不足、传输速度慢的问题。我接手过一个案例:某电商平台…...

告别开发板“失忆”:用Vivado给Artix-7 FPGA的SPI Flash下载程序,并聊聊BIN和MCS该怎么选

告别开发板“失忆”:用Vivado给Artix-7 FPGA的SPI Flash下载程序,并聊聊BIN和MCS该怎么选 想象一下,你花费数周精心调试的FPGA设计,每次断电后就像被施了魔法一样消失无踪——开发板变成了一个"失忆患者"。这种场景对于…...

STM32F103x + ULN2003驱动28BYJ-48步进电机:从开环控制到细分驱动的进阶实践

1. 认识28BYJ-48步进电机与ULN2003驱动模块 第一次拿到28BYJ-48这个小家伙时,我完全没想到它能在我的项目中发挥这么大作用。这款直径28mm的永磁减速步进电机,名字里的每个字母数字都有含义:B代表步进电机,Y表示永磁体&#xff0c…...

BRDF Explorer核心功能深度解析:从Lambert到Disney BRDF的完整探索

BRDF Explorer核心功能深度解析:从Lambert到Disney BRDF的完整探索 【免费下载链接】brdf BRDF Explorer 项目地址: https://gitcode.com/gh_mirrors/br/brdf BRDF Explorer是一款功能强大的开源工具,专为探索和分析双向反射分布函数(…...

腾讯云国际站实名账号LingduCloud零度云:腾讯云国际站实名账号认证教程!!!

做云服务久了,腾讯云国际站代理商LingduCloud零度云 发现一个很有意思的现象:很多人一听到“实名账号认证”,第一反应就自动进入紧张模式,仿佛下一秒要和英文页面、验证码、资料上传、人工审核展开一场拉锯战。其实真没有那么夸张…...

用FPGA复刻一个多功能数字钟:从模块划分到上板调试的完整实战记录

用FPGA打造多功能数字钟:从设计到调试的全流程实战指南 在电子工程和计算机科学领域,FPGA(现场可编程门阵列)因其高度灵活性和并行处理能力,成为数字系统设计的理想平台。本文将带领读者完成一个完整的FPGA项目——多功…...

STM32蓝牙通信避坑指南:没有USB转TTL,如何搞定HC-06的AT指令配置?

STM32蓝牙通信避坑指南:没有USB转TTL,如何搞定HC-06的AT指令配置? 当你手头只有一块STM32开发板和HC-06蓝牙模块,却缺少关键的USB转TTL工具时,AT指令调试就会变成一场噩梦。上周我就遇到了这种情况——项目deadline迫在…...

Veeam Backup 12实战:构建ESXi 7.0 U3虚拟机自动化灾备体系

1. 为什么需要自动化灾备体系 在虚拟化环境中,数据安全永远是头等大事。我见过太多因为硬盘故障、误操作甚至勒索软件导致业务停摆的案例。就拿上周来说,隔壁公司的运维小哥不小心删除了关键虚拟机,结果手头只有一周前的备份,损失…...

IndexMap排序方法大全:stable、unstable和并行排序对比

IndexMap排序方法大全:stable、unstable和并行排序对比 【免费下载链接】indexmap A hash table with consistent order and fast iteration; access items by key or sequence index 项目地址: https://gitcode.com/gh_mirrors/in/indexmap IndexMap是一个兼…...

Notepad--:5个理由告诉你为什么这款国产跨平台编辑器值得一试

Notepad--:5个理由告诉你为什么这款国产跨平台编辑器值得一试 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- …...

从真题到实战:程算I机考核心算法与C语言实现精讲

1. 从真题到实战:程算I机考核心算法解析 第一次接触程算I机考的同学,往往会被各种算法题目弄得手忙脚乱。我当年也是这样,直到后来发现真题才是最好的老师。就拿2023年电子科大的机考真题来说,看似简单的题目背后,其实…...

ChatPDF 开源项目教程

ChatPDF 开源项目教程 【免费下载链接】Open-Generative-AI Uncensored, open-source alternative to Higgsfield AI, Freepik, Krea, Openart AI — Free, unrestricted AI image & video generation studio with 200 models (Flux, Midjourney, Kling, Sora, Veo). No co…...

React TypeScript Cheatsheet:自定义错误边界组件类型终极指南

React TypeScript Cheatsheet:自定义错误边界组件类型终极指南 【免费下载链接】react Cheatsheets for experienced React developers getting started with TypeScript 项目地址: https://gitcode.com/gh_mirrors/reactt/react-typescript-cheatsheet Reac…...