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

TOP-K问题

目录

问题描述

解法及思想

第一种方式

算法思想

具体实现

第二种方式

算法思想

具体实现


问题描述

Top-K问题是一个十分经典的问题,一般有以下两种方式来描述问题:

  • 在10亿的数字里,找出其中最大的100个数;
  • 在一个包含n个整数的数组中,找出最大的100个数。

前边两种问题描述稍有区别,但都是说的Top-K问题,前一种描述方式是说这里也许没有足够的空间存储大量的数字或其他东西,我们最好可以在一边输入数据,一边求出结果,而不需要存储数据;后一种说法则表示可以存储数据,这种情况下,最简单直观的想法就是对数组进行排序,取后100个数即为所求。

解法及思想

第一种方式

这种情况下,关键在于不能消耗太大的内存,无法通过数组的简单排序来求取最大的K个数,于是我们应该想到堆排序,求最大的K个数,就采用大小为K的最小二叉堆来实现;我们知道二叉堆可以看作是一颗近似的完全二叉树,其根节点正好就是K个数中最小的一个。

算法思想

先输入K个数,建立一个大小为K的最小二叉堆,接着每输入一个数,与堆的根节点进行比较,如果比根节点还小,说明不可能为最大的K个数之一,如果比根节点大,那么替换根节点的值,接着下沉根节点,维护二叉堆的性质。这样到成功输入所有数据后,最小二叉堆里剩下的就为最大的K个数。(如果求最小的K个数,同理换成最大二叉堆即可)。

时间复杂度由于算法主要涉及对二叉堆结构的操作,所以总体时间复杂度为O(nlgK)

具体实现

/*
*代码采用STL中的最小优先队列实现,由于STL中自带最小优先队列,其底层就是二叉堆实现,
*所以就不再手写二叉堆了。最小优先队列顶层元素总是队列中最小的元素,也就是二叉堆堆顶。
*/#include <iostream>
#include <queue>
#include <vector>
using namespace std;/*由于STL自带优先队列是默认最大优先的,所以自己写了一个比较函数,将其改为最小优先*/
struct cmp1 {bool operator ()(int &a, int &b) {return a>b;											//最小值优先}
};int main() {//这里用来测试,输入格式:先输入需要求的最大K个数中的K值,再依次输入数据流int K = 0;cin >> K;int tmp = 0;int i = 0;priority_queue<int,vector<int>,cmp1> minHeap;			//建立最小优先队列while (cin >> tmp) {									//循环输入数据流if (i < K) {										//先建立一个K个大小的优先队列,也就是K大小的二叉堆minHeap.push(tmp);}else {												//算法实现if (tmp <= minHeap.top())continue;else if (tmp > minHeap.top()) {minHeap.pop();minHeap.push(tmp);}}i++;}while (!minHeap.empty()) {								//输出最大的K个数cout << minHeap.top() << endl;minHeap.pop();}return 0;
}

第二种方式

这种情况,由于可以操作存储数据的数组,所以我们采用排序的方式进行求解,但一般的排序时间复杂度也挺高,题目只求最大的K个数,不需要完全排序;于是我们想到可以借用快排思想来进行求解。

算法思想

我们知道,每运行一次Partition函数都会确定一个数m的最终位置,且小于m的数均在其左边,大于m的数都在其右边,所以我们的目的就是当数m的右边正好有K-1个数的时候停止算法,得到答案。每次运行Partition函数时,根据前边上述性质,若

  • K<右边数组长度,那么要找的K个数一定在m右边,对m右边的数组运行Partition函数;
  • K=右边数组长度+1,那么正好找到最大的K个数,为数m以及其右边数组,停止算法;
  • 其他情况,最大的K个数不仅仅在m数右边数组中,对m左边数组运行Partition函数。

时间复杂度:与快排类似,Quick Select同样也是不稳定的算法,最坏情况下时间复杂度会达到O(n^2),但平均性能也与快排类似,时间复杂度一般可认为为O(n)。

具体实现

#include <iostream>
#include <vector>using namespace std;void swap(vector<int>&arr, int l, int r)//元素交换函数
{int temp = arr[l];arr[l] = arr[r];arr[r] = temp;
}int Partition(vector<int>&arr, int left, int right)
{int less = left - 1;//选准左边界int more = right;//右边界int temp = arr[right];//选定基准位置while (left < more){if (arr[left] < temp){swap(arr, ++less, left++);//当前元素小于基准元素,左边界内扩}else if (arr[left] > temp)//当前元素大于基准元素,右边界内扩,左边界不变{swap(arr, --more, left);}elseleft++;}swap(arr, more, right);//最后一个基准位置交换return left;//如果存在元素相等情况,返回相同元素两侧的边界索引
}int main() {cout << "请输入K: " << endl;int K = 0;										//测试部分,输入需要求的K值大小,然后再依次输入数组元素cin >> K;int tmp = 0;vector<int> vec = {1,2,6,8,10,50,34,36,27,58,70,66};int size = vec.size();if (size == 0 || K > size)return 0;if (size == K){for (int i = 0; i < size; i++) {			//测试部分,输出需要求的K个数cout << vec[i] << endl;}}int left = 0;int right = vec.size() - 1;int index = Partition(vec, left, right);while (index != size - K) {						//当Partition返回值及右边部分不是K大小时,继续循环int sizeOfRight = size - index - 1;			//记录index右边数组长度大小if (K <= sizeOfRight) {index = Partition(vec, index + 1, right);}else if (K == sizeOfRight + 1)				//这一步好像有点多余,while循环保证了这点,但为了对应博客文字描述就加上了continue;else if (K > sizeOfRight + 1) {index = Partition(vec, left, index - 1);}}cout << "输出TOPK个元素: " << endl;for (int i = index; i < size; i++) {			//测试部分,输出需要求的K个数cout << vec[i] << " ";}cout << endl;return 0;
}


 

相关文章:

TOP-K问题

目录 问题描述 解法及思想 第一种方式 算法思想 具体实现 第二种方式 算法思想 具体实现 问题描述 Top-K问题是一个十分经典的问题&#xff0c;一般有以下两种方式来描述问题&#xff1a; 在10亿的数字里&#xff0c;找出其中最大的100个数&#xff1b;在一个包含n个整…...

【保姆级从0到1】UE5 蓝图入门教程1:关卡、蓝图入门

20230113 1、新建项目 新建选择 UE 5.1 项目 选择蓝图&#xff0c;项目位置 改变编辑器布局&#xff0c;选择经典布局 2、关卡与蓝图 选择 File -> New Level 准备创建关卡 选择 Basic&#xff0c;点击 Create 进行创建 Ctrl S 保存新建的关卡 关卡蓝图的打开 鼠标右键&…...

【码银送书第六期】《ChatGPT原理与实战:大型语言模型的算法、技术和私有化》

写在前面 2022年11月30日&#xff0c;ChatGPT模型问世后&#xff0c;立刻在全球范围内掀起了轩然大波。无论AI从业者还是非从业者&#xff0c;都在热议ChatGPT极具冲击力的交互体验和惊人的生成内容。这使得广大群众重新认识到人工智能的潜力和价值。对于AI从业者来说&#xf…...

redis 报错 Redis protected-mode 配置文件没有真正启动

(error) DENIED Redis is running in protected mode because protected mode is enabled Redis protected-mode 是3.2 之后加入的新特性&#xff0c;在Redis.conf的注释中&#xff0c;我们可以了解到&#xff0c;他的具体作用和启用条件 链接redis 时只能通过本地localhost …...

解决a标签内容中img标签和p标签垂直方向间隔太大的问题

现象如下&#xff1a; 对应的html结构&#xff1a; 解决办法&#xff1a;给a标签设置&#xff1a;display: inline-block和line-height属性。 然后问题解决&#xff1a; 具体原理如下&#xff08;由chatgpt回答&#xff09;&#xff1a; display: inline-block 可以减少垂直方…...

如何选择靠谱的全景平台?VR全景加盟从哪方面对比?

VR全景行业经过近几年的发展&#xff0c;已经逐渐普及开来&#xff0c;线下各个行业都有实体商家开始引入VR全景去做营销宣传推广了。不少老板也意识到线上线下双渠道的重要性&#xff0c;而VR全景的存在就刚好满足各行各业的需求&#xff0c;从这一点不难看出&#xff0c;VR全…...

CentOS系统环境搭建(十八)——CentOS7安装Docker20.10.12和docker compose v2

centos系统环境搭建专栏&#x1f517;点击跳转 CentOS7安装Docker20.10.12和docker compose v2 关于Docker旧版本和docker compose1.0版本的安装可以看这一篇CentOS系统环境搭建&#xff08;三&#xff09;——Centos7安装Docker&Docker Compose。 1.卸载旧版本 卸载do…...

NebulaGrap入门介绍和集群安装部署

长风破浪八千里&#xff0c;落日晚霞不回头。 ——大宁。 NebulaGrap——分布式图数据库 官方文档&#xff1a; ​ NebulaGraph Database手册 ​ 官方文档 介绍 简介&#xff1a; ​ NebulaGraph 一款开源、分布式图数据库&#xff0c;擅长处理超大规模数据集。 Nebula …...

thinkphp5.0 composer 安装oss提示php版本异常

场景复现&#xff1a; 本地 phpstudy 环境&#xff0c;安装的有7.0到7.3三个版本&#xff0c;首先确认composer已经安装 composer安装阿里云oss的命令为&#xff1a;composer require aliyuncs/oss-sdk-php 运行报错&#xff1a; Problem 1- Root composer.json requires php…...

AList dokcer安装及百度网盘挂载

AList是开源的网盘管理工具。本文介绍如何通过docker安装AList并挂载百度网盘 1、AList安装 1.1、系统安装 通过docker命令进行安装&#xff0c;命令如下: docker run -d --restartalways -v /etc/alist:/opt/alist/data -p 5244:5244 --name"alist" xhofe/alist:…...

whereIn 遇到了最大限制,临时表处理方式

当使用whereIn 遇到了限制&#xff0c;比如whereIn target ID 已经超过了10万级别&#xff0c;但是又没办法join其他库表时&#xff0c;可以使用临时表的方式解决&#xff0c;临时表是以一种会话的方式存在&#xff0c;意味着你断开了mysql 这个临时会话会自动销毁。 为了创建…...

基于SSM的校园快递代取系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

MySQL事务详细讲解

文章目录 什么是事务:1.事务有哪些特性2.并发事务会引起什么问题3.事务的隔离级别有哪些4.Read View在MVCC中如何工作Read View 有四个重要的字段使用 InnoDB 存储引擎的数据库表&#xff0c;它的聚簇索引记录中都包含下面两个隐藏列&#xff1a; 5.可重复读是怎么工作的6.读提…...

[linux] mmcv-full 安装的时候 Building wheel 卡住

&#xff08;已解决&#xff09;FileNotFoundError: [Errno 2] No such file or directory: ‘:/usr/local/cuda-11.8/bin/nvcc‘_鳗小鱼的博客-CSDN博客 安装mmcv一直卡在建车轮_梦想成为大佬的王老八的博客-CSDN博客 pip install -U openmim mim install mmcv...

Python怎么实现更高效的数据结构和算法? - 易智编译EaseEditing

要实现更高效的数据结构和算法&#xff0c;你可以考虑以下几个方面的优化&#xff1a; 选择合适的数据结构&#xff1a; 选择最适合你问题的数据结构至关重要。例如&#xff0c;如果需要频繁插入和删除操作&#xff0c;可能链表比数组更合适。如果需要高效查找操作&#xff0…...

03-zookeeper节点动态上下线案例

服务器动态上下线监听案例 需求 在分布式系统中&#xff0c;主节点可以有多台&#xff0c;可以动态上下线&#xff0c;任意一台客户端都能实时感知到主节点服务器的上下线。 需求分析 客户端能实时洞察到服务器上下线的变化 基本流程&#xff1a; ​ 1.服务端启动时去注册…...

如何使用TensorFlow完成线性回归

线性回归是一种简单的预测模型&#xff0c;它试图通过线性关系来预测目标变量。在TensorFlow中&#xff0c;我们可以使用tf.GradientTape来跟踪我们的模型参数的梯度&#xff0c;然后用这个信息来优化我们的模型参数。 以下是一个简单的线性回归的例子&#xff1a; pythonimpo…...

@controller和@RestController的区别

//controller和RestController的区别:RestController的返回值就是结果被输出在浏览器 //controller的返回值会到resources的templates下找 返回值".html" 页面 1.controller 简单的来说&#xff0c;当我们的返回值需要跳转大另一个页面时候&#xff0c;我们就会使…...

GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 论文阅读

论文信息 题目&#xff1a;GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 作者&#xff1a;Zhichao Yin and Jianping Shi 来源&#xff1a;CVPR 时间&#xff1a;2018 Abstract 我们提出了 GeoNet&#xff0c;这是一种联合无监督学习框架&a…...

蓝桥杯官网填空题(振兴中华)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小明参加了学校的趣味运动会&#xff0c;其中的一个项目是&#xff1a;跳格子。 地上画着一些格子&#xff0c;每个格子里写一个字&#xff0c;如下所示&#xff1…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...