寻找第K大的数字

寻找第k大的数字,有很多方法,最基本的就是将数组按照从大到小的顺序排列,找出第k个元素即可。但是这种方法的时间复杂度为o(nlog(n)),我们还能找到更好地方法。下面我们将介绍另外两种办法,一种是基于快排Partition的方法,一种是基于partial_sort的方法。

基于快排partition的查找法

利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:

  1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
  2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)

递归法

#include <iostream>using namespace std;//快速排序的划分函数
int partition(int data[],int i,int j)
//将>=x的元素换到左边区域
//将<=x的元素换到右边区域
{if(data==NULL||i<0)throw std::exception("invalued parameter");int index = i+rand()%(j-i+1);//生产随机数int pivot=data[index];swap(data[i],data[index]);while(i<j){while(i<j&&pivot>=data[j]){j--;}if (i<j){data[i++]=data[j];}while(i<j&&pivot<=data[i]){i++;}if (i<j){data[j--]=data[i];}}data[i]=pivot;return i;
}//线性寻找第k大的数,递归法
int random_select(int a[],int l,int r,int k)
{if(k>(r-l+1)||k<1)//k应该在[1,r-l+1]之间throw std::exception("invalued k");int i,j;if (l == r) //递归结束{return a[l];}i = partition(a,l,r);//划分j = i-l+1;//距开始的长度,i为第j大的数字if(k == j) //递归结束,找到第K大的数return a[i];if(k < j){return random_select(a,l,i-1,k);//递归调用,在前面部分查找第K大的数}elsereturn random_select(a,i+1,r,k-j);//递归调用,在后面部分查找第K大的数
}int main()
{int a[]={1,2,3,4,6,6,7,8,10,10};cout<<random_select(a,0,9,1)<<endl;cout<<random_select(a,0,9,5)<<endl;return 0;
}

循环法

#include <iostream>using namespace std;//快速排序的划分函数
int partition(int data[],int len, int i, int j)
//将>=x的元素换到左边区域
//将<=x的元素换到右边区域
{if (data == NULL ||len<=0|| i < 0||j>=len)throw std::exception("invalued parameter");int index = i + rand() % (j - i + 1);//生产随机数int pivot = data[index];swap(data[i], data[index]);while (i < j){while (i < j&&pivot >= data[j]){j--;}if (i < j){data[i++] = data[j];}while (i < j&&pivot <= data[i]){i++;}if (i<j){data[j--] = data[i];}}data[i] = pivot;return i;
}//线性寻找第k大的数,循环法
int random_select(int a[],int len, int k)
{if (a == NULL || len <= 0 || k > len || k <= 0){throw std::exception("invalued parameter");}int i = 0;int j = len - 1;int index = partition(a, len, i, j);while (index+1!= k){if (index+1> k){index = partition(a, len, i, index - 1);}else{index = partition(a, len, index + 1, j);}}int result = a[k-1];return result;}int main()
{int a[] = { 1, 2, 3, 4, 6, 6, 7, 8, 10, 10 };cout << random_select(a,10, 1) << endl;cout << random_select(a, 10,3) << endl;return 0;
}

上面两种办法均是基于partiton的方法,实际上在C++ STL中也有一个实现查找第k大元素的方法:nth_element.

nth_element

nth_element用于排序一个区间,它使得位置n上的元素正好谁全排序情况下的第n个元素,而且,当nth_element返回的时候,所有按照全排序规则排在位置n之前的元素也都排在位置n之前,按照全排序规则排在n之后的元素全都排在位置n之后。
所以,我们使用nth_element既可以寻找最好的前k个元素,也可以寻找第k大元素。

先看示例:

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{int a[10] = { 8, 9, 1, 2, 4, 3, 5, 6, 7, 10 };nth_element(a, a + 5, a + 10, std::greater<int>());cout << "数组中的中间元素是" << a[5] << endl;nth_element(a, a, a + 10, std::greater<int>());cout << "数组中第1大元素为" << a[0] << endl;nth_element(a, a + 1, a + 10, std::greater<int>());cout << "数组中第2大元素是" << a[1] << endl;
}

结果为:

数组中的中间元素是5
数组中第1大元素为10
数组中第2大元素是9
请按任意键继续. . .

使用说明:

default (1) 
template <class RandomAccessIterator>void nth_element (RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last);
custom (2)  
template <class RandomAccessIterator, class Compare>void nth_element (RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last, Compare comp);

default (1) 使用‘<’作为比较符
custom (2) 可以指定比较运算
nth:实际指的是nth+1大(小)元素,也就是如果你要找前20个最大的,nth=19.

基于partial_sort的查找法

用O(4*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)
在C++ STL中同样有一个部分排序的函数就是partial_sort。
用法:

default (1) 
template <class RandomAccessIterator>void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last);
custom (2)  
template <class RandomAccessIterator, class Compare>void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last, Compare comp);

default (1) :使用‘<’作为比较符
custom (2) :可以指定比较运算
middle:将前middle个元素排序,比如说我们要找到前10个最小的元素,而且从小到大排列,这时可以使用partial_sort,middle=10.
注意
partial_sort与上面的nth_element相比,需要对前面最好的n个元素排序,而nth_element只需要找到前面最好的n个元素就可以,不需要知道顺序。
而且关于第二个参数的使用上截然不同:partial_sort使用第1个和第2个迭代器指明一段需要排序的区间,根据STL关于区间的定义,第2个参数应该是目标区间外的第一个元素(比如widgets.begin()+20实际指的是第21个元素),而nth_element则使用第2个参数标识出容器中的某个特定位置(比如widgets.begin()+19实际指的是第20个元素)
详细情况请参考:《理解你的排序操作[(stable_sort,sort,partial_sort,nth_element,stable_partition,partition)》
因此我们可以先部分排序,再直接取第k个元素即可。

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{int a[10] = { 8, 9, 1, 2, 4, 3, 5, 6, 7, 10 };partial_sort(a, a + 6, a + 10, std::greater<int>());cout << "数组中的中间元素是" << a[5] << endl;partial_sort(a, a + 2, a + 10, std::greater<int>());cout << "数组中第1大元素为" << a[0] << endl;partial_sort(a, a + 3, a + 10, std::greater<int>());cout << "数组中第2大元素是" << a[1] << endl;
}

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

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

相关文章

(12)MSP430F5529 常用内置函数和一些说明

&#xff08;1&#xff09; MSP430F5529支持最高工作频率为25MHZ&#xff0c;也就是说你通过 锁相环倍频来提高系统运行速度是有一个限制的&#xff0c; 最高只能到25MHZ&#xff08;再高没意思了&#xff09;。 &#xff08;2&#xff09;几个重要的内联函数 &#xff08;内联…

从零开始学android编程_android初学者的入门秘籍

大概是去年年底开始接触android原本是学习嵌入式的我&#xff0c;领导让我看看能不能搞一下这个android APP。一开始的我懵逼得很。。。这android APP 不是得用java写吗&#xff1f;&#xff1f;&#xff1f; 现在我看网上说比较多还是用kotlin&#xff0c;没去学。。。好家伙&…

修改了sql默认路径无法登录服务器,PostgreSQL错误'无法连接到服务器:没有这样的文件或目录'...

像其他一些人一样,当我在我的项目中运行rake db:migrate或者甚至为我的Ruby on Rails 3.2应用程序尝试大多数数据库任务时,我收到此错误.PGError(无法连接到服务器:没有这样的文件或目录.服务器是否在本地运行并接受Unix域套接字上的连接"/tmp/.s.PGSQL.5432"&#x…

QMarkDowner编译

第一次完整的编译一个工程。哈哈 记录一下 准备环境 我的环境是win7 x64, python2.7.5 x64的。 python 3.x的我没试过,有需要的朋友可以试一下。 安装python2.7.5 x64 确保将安装路径加入到Path中 PyQt4 啊 我的环境是win的 当然要下win版 (PyQt4-4.10.3-gpl-Py2.7-Qt4.8.5-x6…

C++ STL的查找算法

假设你有一个序列容器&#xff0c;或者有一对迭代器标识了一个区间,现在你希望在容器中查找一些信息&#xff0c;这样的查找工作如何进行呢&#xff1f;你的选择往往是&#xff1a; count,count_if,find,find_if,binary_search,lower_bound,upper_bound,equal_range.该如何选择…

习题七

umask 022 &#xff0c;请描述该命令的含义创建目录时默认的权限为&#xff1a;755 rwxr-xr-x创建文件时默认的权限为&#xff1a;644 rw-r--r--note:创建文件的默认权限是拿掉了X 所以最大为666&#xff0c;而目录最大为777 umask NUM 就是去掉相应的权限转载于:https://blo…

web中的cookie管理

本篇是以JSP为背景介绍&#xff0c;但是在web开发中也是相同的原理。 什么是cookie 由于http是一种无状态的协议&#xff0c;因此服务器收到请求后&#xff0c;只会当做一次新的请求。即便你重复发送了1000次同样的请求&#xff0c;这1000次都属于独立的请求。 这样显然效率很低…

unity怎么设置游戏页面_杭州有没有正规的unity游戏开发培训机构?

现在Unity游戏开发是个火热的行业&#xff0c;薪资待遇比较高&#xff0c;未来的发展方向和前景也比较不错&#xff0c;很多人也都想成为专业Unity游戏开发工程师&#xff0c;学习Unity游戏开发已经成为很多追求更好就业前景的人的选择。学习专业、系统的Unity游戏开发知识并达…

VC++ 使用attributes定义接口

1.定义预处理命令_ATL_ATTRIBUTES 2.在一个全局的Cpp文件里面配置module的attribute [module(dll, uuid "{3845951F-15B8-4286-8E7D-E9D4F5C7B6CE}", name "TestApp")]3.定义接口 [object,uuid("9F414A8A-1D5E-4aff-A60E-CFD65155ABB6"),dual,…

h3c 虚拟服务器 下一跳,H3CNE 312题和313题 直连路由静态路由的下一跳问题

321.在MSR 路由器上看到路由表里有如下显示&#xff1a; Destination/Mask Proto Pre Cost NextHop Interface 127.0.0.0/8 Direct 0 0 127.0.0.1 InLoop0 127.0.0.1/32 Direct 0 0 127.0.0.1 InLoop0 192.168.96.0/19 Direct 0 0 192.168.120.153 S6/0 那么关于目的地321.在MS…

C++成员变量的初始化顺序问题

先来看两道题&#xff1a; // count algorithm example #include <iostream> // std::cout #include <algorithm> // std::count #include <vector> // std::vector using namespace std; class A { public:A() { cout << "in A()&q…

Knockout.Js案例一Introduction

在这第一个教程中,您将体验的一些基本知识构建的web UI Model-View-ViewModel使用knockout.js(MVVM)模式。案例1&#xff1a;添加:data-bind <p>First name: <strong data-bind"text:firstName">1</strong></p><p>Last name: <stro…

C#注册表常用操作

1&#xff1a;加键 改值 Microsoft.Win32.RegistryKey Key Microsoft.Win32.Registry.CurrentUser.CreateSubKey( "Software\Microsoft\Internet Explorer\Main"); Key.SetValue( "Window Title" , value ); Key.Close(); …

谷歌浏览器外贸版_做外贸快两个月,没有单怎么办?

Hello 大家好&#xff0c;我是Jack。今天给大家更新一篇在知乎看到的外贸问题&#xff1a;做外贸快两个月&#xff0c;没有单怎么办?外贸这个话题在知乎算是小众话题了&#xff0c;相比较于职场&#xff0c;英语学习&#xff0c;国际政治&#xff0c;IT等&#xff0c;这些话题…

React Native通信机制详解

http://blog.cnbang.net/tech/2698/ React Native是facebook刚开源的框架&#xff0c;可以用javascript直接开发原生APP&#xff0c;先不说这个框架后续是否能得到大众认可&#xff0c;单从源码来说&#xff0c;这个框架源码里有非常多的设计思想和实现方式值得学习&#xff0c…

C++11系列学习之四----auto

在哪些情况下要申明类型&#xff1a; 定义变量类型 函数返回值&#xff0c;函数参数 表达式返回变量类型 auto关键字原理 在定义变量的时候必须申明类型&#xff0c;c是强语言类型&#xff0c;在编译阶段需要知道类型&#xff0c;这样的好处是程序效率更高&#xff0c;而…

windows 自动copy远程服务器文件

net use h: \\123.45.67.000\T1dbbackup 123456/user:administrator ------远程服务器IP123.45.67.000 。T1dbbackup&#xff1a;共享文件夹 。 h :映射到本机的盘符。 用户名&#xff1a;administrator&#xff0c;密码&#xff1a;123456copy h:\*.* f:\T1DB ------复…

eclipse 不能切换输入法

按了AltShift键&#xff1f;再按一次把EN切换成CN&#xff0c;然后再CtrlShift就可以切换输入法转载于:https://www.cnblogs.com/jiayonghua/p/3413827.html

excel打开2个独立窗口_谢楠称女性独立的不是钱是心 谢楠与吴京婚后生育2个儿子...

近日&#xff0c;在综艺节目《幸福三重奏》 三日谈妻子篇中&#xff0c;谢楠被问到如何看待独立女性时&#xff0c;反问记者会不会问吴京同样的问题&#xff1b;随后回答道&#xff0c;女性独立的不是钱&#xff0c;而是你的心&#xff1b;楠姐的回答超级霸气了&#xff0c;你们…

C++11系列学习之五-------decltype

使用场景 在C中经常要用到很长的变量名&#xff0c;如果已经有变量和你将使用的变量是一个类型&#xff0c;即可使用decltype关键字 来申明一样的类型变量。 decltype原理 返回现有变量类型&#xff0c;decltype是一个关键字&#xff0c;而不是一个函数&#xff0c;这有啥区别…