求一无序数组中第n大的数字 - 快速选择算法
逛别人博客的时候,偶然看到这一算法题,顺便用C++实现了一下。
最朴素的解法就是先对数组进行排序,返回第n个数即可。。
下面代码中用的是快速选择算法(不晓得这名字对不对)
#include <vector>
#include <iostream>
#include <stdexcept>
#include <cstdio> const int QS_EERRMSG_LEN = ; /**
* 快速选择求无序数组中第n大的数字
* 因为select返回的是数组中对象的引用,
* 所以错误处理选择了异常
*/
template <typename T>
class QuickSelect
{
public:
typedef typename std::vector<T>::size_type size_type; /**
* 构造函数
* @brief QuickSelect
* @param array - vector类型的数组
*/
QuickSelect(std::vector<T>& array)
:m_array(array)
{} /**
* 选择第nth大的元素,
* 失败抛出std::out_of_range异常,
* 成功返回得到的元素
* @brief select
* @param nth
* @return
*/
const T&
select(size_type nth) throw(std::out_of_range)
{
//s_pos即第n大在排序之后数组中的下标
size_type s_pos = m_array.size() - nth; if(s_pos > m_array.size()){
char errmsg[QS_EERRMSG_LEN]; std::snprintf(errmsg, QS_EERRMSG_LEN, "Array access violation:{access:%ld range_length:%ld begin:%ld}.", nth, m_array.size(), );
std::out_of_range oor(errmsg);
throw oor;
} return this->select_pos(s_pos, , m_array.size());
} /**
* @brief select
* @param nth
* @param begin
* @param end
* @return
*/
const T&
select(size_type nth, size_type begin, size_type end) throw(std::out_of_range)
{
size_type array_size = m_array.size(); if(begin > array_size || end > array_size || end < begin){
char errmsg[QS_EERRMSG_LEN]; std::snprintf(errmsg, QS_EERRMSG_LEN, "The begin or end are not correct:{array_size:%ld begin:%ld end:%ld}.", array_size, begin, end);
std::out_of_range oor(errmsg);
throw oor;
} //要查找范围的长度
size_type range_length = end - begin + ; //要查找的第n大的元素在当前范围内的位置
size_type s_pos = range_length - nth; if(s_pos > range_length){
char errmsg[QS_EERRMSG_LEN]; std::snprintf(errmsg, QS_EERRMSG_LEN, "Array access violation:{access:%ld range_length:%ld begin:%ld}.", nth, range_length, begin);
std::out_of_range oor(errmsg);
throw oor;
}
else return this->select_pos(s_pos, begin, end);
}
private:
/**
* pos表示的是元素从begin开始的位置
* @brief select_pos
* @param pos
* @param begin
* @param end
* @return
*/
const T& select_pos(size_type pos, size_type begin, size_type end)
{
T& pivot = m_array[begin];
size_type swap_pos = begin; if(begin == end){
return m_array[pos];
} //进行一次快速排序
for(size_type i = begin + ;i < end;i ++){
if(m_array[i] < pivot){
std::swap(m_array[i], m_array[swap_pos ++]);
}
} //数组元素个数为奇数时多交换一次
if(m_array.size() % != ){
if(m_array[end - ] < pivot){
std::swap(m_array[end - ], m_array[swap_pos ++]);
}
} if(swap_pos - begin == pos){
return m_array[swap_pos];
}
else if(swap_pos - begin < pos){
return this->select_pos(pos, swap_pos + , end);
}
else{
return this->select_pos(pos, begin, swap_pos);
}
} /**
* @brief m_array
*/
std::vector<T>& m_array;
};
然后为了测试方便,实现vector输出,很简单的输出
namespace std{
template <typename T>
std::ostream& operator <<(std::ostream& out, const std::vector<T>& array)
{
for(auto e:array){
out << e <<" ";
}
out <<std::endl;
return out;
}
}
下面是测试用例
int main()
{
std::vector<int> some{,,,,}; std::cout <<some; QuickSelect<int> qs(some); std::cout <<qs.select()<<std::endl; return ;
}
结果输出为
[root@localhost MYJOURNEY]# g++ quick_select.cpp -std=c++
[root@localhost MYJOURNEY]# ./a.out [root@localhost MYJOURNEY]#
求一无序数组中第n大的数字 - 快速选择算法的更多相关文章
- 无序数组中第Kth大的数
题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...
- [LeetCode] Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 前端算法题:找出数组中第k大的数字出现多少次
题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...
- 无序数组中第K大的数
1. 排序法 时间复杂度 O(nlogn) 2. 使用一个大小为K的数组arr保存前K个最大的元素 遍历原数组,遇到大于arr最小值的元素时候,使用插入排序方法,插入这个元素 时间复杂度,遍历是 O( ...
- 查找无序数组中第K大的数
思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...
- 如何寻找无序数组中的第K大元素?
如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...
- SQL Server 2008 R2——查找最小nIndex,nIndex存在而nIndex+1不存在 求最小连续数组中的最大值
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- 快速查找无序数组中的第K大数?
1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高 ...
随机推荐
- Flask学习记录之Flask-SQLAlchemy
Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命令. Flask-Migrate ...
- python中的StringIO模块
python中的StringIO模块 标签:python StringIO 此模块主要用于在内存缓冲区中读写数据.模块是用类编写的,只有一个StringIO类,所以它的可用方法都在类中.此类中的大部分 ...
- Small factorials Solved Problem code: FCTRL2
import sys def fact(n): final = n while n > 1: final *= n - 1 n -= 1 return final #逻辑严谨,不要忘了retur ...
- python文件_改名2
#手动选择路径,批量改名 import os,re,time,tkFileDialog global i #文件名后面增加后缀:txt,png,bng,jpeg,jpg,gif,zip类型的文件 de ...
- Linux_Shell type
Recommendation is to use the bash shell, because he is strong enough, and absorbed the useful proper ...
- iOS开发之MD5封装及应用
一.MD5的封装 #define CC_MD5_DIGEST_LENGTH 16 - (NSString *)toMD5 { const char* input = [self UTF8String] ...
- [Ioi2007]Miners 矿工配餐(BZOJ1806)
[Ioi2007]Miners 矿工配餐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 214 Solved: 128 Description 现有两 ...
- XJOI网上同步训练DAY1 T2
思路:似曾相识?...见http://www.cnblogs.com/qzqzgfy/p/5266874.html 一看时限还是4s!,于是就开开心心地打了70%的分,就是用容斥原理,就可以n^3解决 ...
- LeetCode_Surrounded Regions
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...
- GestureDetector和SimpleOnGestureListener的使用教程
1. 当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(Vi ...