Top K问题及解决

Top K问题及解决

Top K问题:在大规模数据处理中,经常会需要在海量数据中找出频率最高的前K个数。比如,在搜索引擎中,统计搜索最热门的10个查询词等。针对Top K类问题,可以使用分治算法+Trie树/hash + 小/大顶堆,事先把数据集按照Hash方法分解成多个小数据集,然后使用Trie树或者Hash统计每个小数据集中查询词的频率,之后用小/大顶堆求出每个数据集中出现频率最高的前K个数,最后在所有Top K中求出最终的Top K。

  1. 以在10亿个数中找出前10个为例,java中可以使用优先队列来解决,优先队列可以保证在常数时间内插入元素,并且能在对数时间内提供最大或最小元素,优先队列默认使用元素的自然顺序,不是线程安全的,在高并发情况下使用时需要加锁,用数组存储二叉树节点。
package org.dsg.arith;import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;public class Top10Solution {public static void main(String[] args) {Queue<Integer> top10 = new PriorityQueue<>(11, (a, b) -> b-a);Random random = new Random();for (int i=0;i<1000000000;i++) {int num = random.nextInt()%100;if (top10.size() < 10) {top10.offer(num);} else if (num > top10.peek()) {top10.poll();top10.offer(num);}}		System.out.println(top10);}}

运行结果:

[99, 66, 50, 33, 57, 34, -89, -91, -79, -8]

  1. 部分方法介绍
//把元素添加到队列中,元素个数加一,添加成功返回true,队列空间不够会进行扩容
public boolean offer(E e) {if (e == null)throw new NullPointerException();modCount++;int i = size;if (i >= queue.length)grow(i + 1);size = i + 1;//队列为空,则直接把元素添加到队头if (i == 0)queue[0] = e;elsesiftUp(i, e);return true;
}//数组扩容
private void grow(int minCapacity) {int oldCapacity = queue.length;// Double size if small; else grow by 50%int newCapacity = oldCapacity + ((oldCapacity < 64) ?(oldCapacity + 2) :(oldCapacity >> 1));// overflow-conscious codeif (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);queue = Arrays.copyOf(queue, newCapacity);
}//把x值插入到位置i,一个使用比较器,另一个不使用
private void siftUp(int k, E x) {    if (comparator != null)siftUpUsingComparator(k, x);elsesiftUpComparable(k, x);
}//使用lambda实现的从大到小的比较器为例
private void siftUpUsingComparator(int k, E x) {while (k > 0) {//获取父节点索引 1 >>> 1 = 0int parent = (k - 1) >>> 1;Object e = queue[parent];//待插入值比父节点值小则退出if (comparator.compare(x, (E) e) >= 0)break;        //待插入节点值比父节点值大,把父节点值放到待插入索引queue[k] = e;//更新需要插入的位置为父节点的位置,重复操作k = parent;}queue[k] = x;
}private void siftUpComparable(int k, E x) {Comparable<? super E> key = (Comparable<? super E>) x;while (k > 0) {int parent = (k - 1) >>> 1;Object e = queue[parent];if (key.compareTo((E) e) >= 0)break;queue[k] = e;k = parent;}queue[k] = key;
}//从队列中取出队头元素,元素个数减一,取出队尾元素后调整队列
public E poll() {if (size == 0)return null;int s = --size;modCount++;E result = (E) queue[0];E x = (E) queue[s];queue[s] = null;if (s != 0)siftDown(0, x);return result;
}//把x值插入到位置k, x向下传递直到小于等于子节点或者是叶子节点
private void siftDown(int k, E x) {if (comparator != null)siftDownUsingComparator(k, x);elsesiftDownComparable(k, x);
}//以k=0,x为队尾元素为例
private void siftDownUsingComparator(int k, E x) {//队列个数折半int half = size >>> 1;while (k < half) {//当k=0时,child=1为左子节点索引int child = (k << 1) + 1;Object c = queue[child];//右子节点索引int right = child + 1;//当右子节点小于一半值,并且右子节点值大于左子节点时,把c置为较大值if (right < size &&comparator.compare((E) c, (E) queue[right]) > 0)c = queue[child = right];//比较待插入值x与c,如果x比c要打,则把x插入到k的位置if (comparator.compare(x, (E) c) <= 0)break;queue[k] = c;k = child;}queue[k] = x;
}private void siftDownComparable(int k, E x) {Comparable<? super E> key = (Comparable<? super E>)x;int half = size >>> 1;        // loop while a non-leafwhile (k < half) {int child = (k << 1) + 1; // assume left child is leastObject c = queue[child];int right = child + 1;if (right < size &&((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)c = queue[child = right];if (key.compareTo((E) c) <= 0)break;queue[k] = c;k = child;}queue[k] = key;
}//获取队头元素
public E peek() {return (size == 0) ? null : (E) queue[0];
}

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

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

相关文章

Go 语言条件变量 Cond

1.Cond 的使用方法 Go 标准库提供 Cond 同步原语的目的是为等待/通知场景下的并发操作提供支持。Cond 通常用于等待某个条件的一组 goroutine,当条件变为 true 时,其中一个或者所有的 goroutine 会被唤醒执行。 Cond 与某个条件相关,这个条件需要一组 goroutine 协作达到。当这…

HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 多选题序号5

基础认证题库请移步&#xff1a;HarmonyOS应用开发者基础认证题库 注&#xff1a;有读者反馈&#xff0c;题库的代码块比较多&#xff0c;打开文章时会卡死。所以笔者将题库拆分&#xff0c;单选题20个为一组&#xff0c;多选题10个为一组&#xff0c;题库目录如下&#xff0c;…

【学一点儿前端】getaddrinfo ENOTFOUND registry.nlark.com“.

问题 今天jenkins打包一个项目&#xff0c;发现报错了 error An unexpected error occurred: "https://registry.nlark.com/xxxxxxxxxx.tgz: getaddrinfo ENOTFOUND registry.nlark.com". 先写解决方案 把yarn.lock文件里面的registry.nlark.com替换为registry.npmmi…

<数据集>抽烟识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;4860张 标注数量(xml文件个数)&#xff1a;4860 标注数量(txt文件个数)&#xff1a;4860 标注类别数&#xff1a;1 标注类别名称&#xff1a;[smoking] 使用标注工具&#xff1a;labelImg 标注规则&#xff1a;对…

Python3 第四十课 -- 实例九

目录 一. 十进制转二进制、八进制、十六进制 1.1. 二进制转换实例 1.2. 八进制转换实例 1.3. 十六进制转换实例 一. 十进制转二进制、八进制、十六进制 以下代码用于实现十进制转二进制、八进制、十六进制&#xff1a; # -*- coding: UTF-8 -*-# Filename : test.py # au…

uni-app云函数中使用mqtt接收消息

const mqtt require(mqtt);exports.main async (event, context) > {return new Promise((resolve, reject) > {// 连接到 MQTT 服务器const client mqtt.connect(wss://mqtt.example.com:8083/mqtt, {username: your-username,password: your-password,});// 连接成功…

spring —— spring 整合 junit

如果不使用 spring 整合 junit&#xff0c;每次取对象时都要建立 spring 容器&#xff0c;然后从 spring 容器中提取对象&#xff0c;也就是以下两行代码&#xff1a; //建立spring容器 ApplicationContext context new ClassPathXmlApplicationContext("xxx.xml")…

探索 IPython %%sql 魔术:数据库交互的高效工具

探索 IPython %%sql 魔术&#xff1a;数据库交互的高效工具 在数据科学和分析领域&#xff0c;IPython 提供了一个强大的交互式环境&#xff0c;允许用户执行 Python 代码并与各种数据源进行交互。%%sql 魔术命令是 IPython 环境中的一个特殊命令&#xff0c;它允许用户直接在…

【时间动作定位】End-to-end Temporal Action Detection with Transformer 论文阅读

End-to-end Temporal Action Detection with Transformer 论文阅读 AbstractI. INTRODUCTIONII. RELATED WORKIII. TADTRA. ArchitectureB. Training and Inference IV. EXPERIMENTSV. CONCLUSION 文章信息&#xff1a; 发表于&#xff1a; IEEE Transactions on Image Proce…

四、GD32 MCU 常见外设介绍 (7) 7.I2C 模块介绍

7.1.I2C 基础知识 I2C(Inter-Integrated Circuit)总线是一种由Philips公司开发的两线式串行总线&#xff0c;用于内部IC控制的具有多端控制能力的双线双向串行数据总线系统&#xff0c;能够用于替代标准的并行总线&#xff0c;连接各种集成 电路和功能模块。I2C器件能够减少电…

【MQTT协议与IoT通信】MQTT协议的使用和管理

MQTT协议与IoT通信&#xff1a;MQTT协议的使用和管理 目录 引言MQTT协议概述 什么是MQTTMQTT的工作原理 MQTT协议的关键特性 轻量级与高效性发布/订阅模式质量服务等级(QoS)持久会话安全性 MQTT协议的使用方法 设置MQTT Broker连接MQTT Client发布消息订阅主题断开连接 MQTT协…

策略+工厂设计模式的应用

问题 比如有下面一段业务&#xff0c;一个自动售货机&#xff0c;根据用户选择不同的饮料&#xff0c;出对应的货 public class NoDesignDemo {public void ifElse(String parameter) {if ("Pepsi".equalsIgnoreCase(parameter)) {System.out.println("百事可…

[ptrade交易实战] 第十八篇 期货查询类函数和期货设置类函数

前言 今天主要和大家分享的是期货查询类的函数和期货设置类的函数&#xff01; 具体的开通渠道可以看文章末尾&#xff01; 一、get_margin_rate—— 获取用户设置的保证金比例 保证金是期货交易中的一个重点&#xff0c;这个函数就是用来获取我们设置的保证金比例的&#…

整合StarRocks主键表全部知识点

总结StarRocks主键表的全部内容的集合&#xff08;V3.2版本&#xff09; 一、基本功能 主键非空约束&#xff0c;任何一个字段都不可以为空支持导入数据时删除数据操作(CDC)支持部分更新支持独立的排序键&#xff08;只有主键表支持独立排序键&#xff0c;而且可以不为key键&…

极限科技闪耀 2024 可信数据库发展大会,多款自研产品引领搜索技术新纪元

北京&#xff0c;7 月 16、17 日 —— 在由中国信息通信研究院&#xff08;中国信通院&#xff09;与中国通信标准化协会联合主办&#xff0c;InfoQ 协办的“2024 可信数据库发展大会”&#xff08;TDBC 2024&#xff09;上&#xff0c;极限科技凭借其前沿的搜索技术创新与卓越…

【相机与图像】1. 相机模型的介绍:内参、外参、畸变参数

想着整理下相机模型&#xff08;内容上参考 slam十四讲&#xff09;、相机的内外参标定。方便自己的使用和回顾。 不过&#xff0c;内外参标定啥时候记录随缘 -_- 概述 【构建相机模型】 相机将三位世界中的坐标点&#xff08;单位为米&#xff09;映射到二维图像平面&#xff…

py Qt5学习记录

1.Qt5的安装 可参考一些博客如&#xff1a;Python 小白从零开始 PyQt5 项目实战&#xff08;2&#xff09;菜单和工具栏_pyqt 二级菜单-CSDN博客 2.Qt5的界面显示 3.新建一个工具栏并打开本地文件方法 &#xff08;1&#xff09;在Qt5界面右下角有个“动作编辑器”&#xff…

学习笔记5:缓存穿透

缓存穿透 缓存穿透是指在缓存系统中&#xff0c;当一个请求的查询结果为空时&#xff0c;这个请求会直接穿透缓存系统&#xff0c;访问后端的数据库。如果这种情况频繁发生&#xff0c;会对数据库造成较大的压力&#xff0c;甚至可能导致数据库崩溃。 在正常情况下&#xff0…

对pytorch optimizer中state_dict、state、param_groups的简要理解

先说结论&#xff1a; state_dict()&#xff1a;一个dict&#xff0c;里面有两个key&#xff08;state和param_groups&#xff09;&#xff0c; state这个key对应的value是各个权重对应的优化器状态。具体来说&#xff0c;一个model有很多权重&#xff0c;model.parameters()会…

MyBatis相关问题汇总

sql预编译原理 https://www.cnblogs.com/Createsequence/p/16963891.html MyBatis一级缓存&二级缓存 mybatis的缓存机制&#xff08;一级缓存二级缓存和刷新缓存&#xff09;和mybatis整合ehcache_mybatis缓存机制-CSDN博客