快速排序/快速查找(第k个, 前k个问题)
//快速排序:Partition分割函数,三数中值分割
bool g_bInvalidInput = false;
int median3(int* data, int start, int end){
int middle = (start + end) >> 1;
if (data[start] > data[middle])
std::swap(data[start], data[middle]);
if (data[start] > data[end])
std::swap(data[start], data[end]);
if (data[middle] > data[end])
std::swap(data[middle], data[end]);
std::swap(data[middle], data[end - 1]);
return data[end - 1];
}
int Partition(int* data, int length, int start, int end){
if (data == nullptr || length <=0 ||start < 0 || end > length - 1){
g_bInvalidInput = true;
return 0;
}
int pivot = median3(data, start, end);
int i = start;
int j = end - 1;
for (;;){
while (data[++i] < pivot) {;}
while (data[--j] > pivot) {;}
if (i < j)
std::swap(data[i], data[j]);
else
break;
}
std::swap(data[i], data[end - 1]);
return i;
}
void QuickSort(int* data, int length, int start, int end){
if (start == end)
return;
int pivotIdx = Partition(data, length, start, end);
if (pivotIdx > start){
QuickSort(data, length, start, pivotIdx - 1);
}
if (pivotIdx < end){
QuickSort(data, length, pivotIdx + 1, end);
}
}
void QuickSortPort(int* data, int length){
if (data == nullptr || length <= 0)
return;
QuickSort(data, length, 0, length - 1);
}
//快速排序:随机选取枢纽元, Partition分割函数
#include <stdlib.h>
#include <time.h>
int randomInRange(int start, int end){
srand((unsigned int)(time(NULL)));
if (start == end)
return start;
else if (end < start)
return end + rand() % (start - end + 1);
else {
return start + rand() % (end - start + 1);
}
}
bool g_bInvalidInput = false;
int Partition(int* data, int length, int start, int end){
if (data == nullptr || length <= 0 || start < 0 || end > length - 1){
g_bInvalidInput = true;
return 0;
}
int pivotIdx = randomInRange(start, end);
int pivot = data[pivotIdx];
std::swap(data[pivotIdx], data[end]);
int i = start - 1;
int j = end;
for (; i <= end && j >= start; ){
while (++i <= end && data[i] < pivot) {;}
while (--j >=start && data[j] > pivot) {;}
if (i < j){
std::swap(data[i], data[j]);
}
else
break;
}
std::swap(data[i], data[end]);
return i;
}
void QuickSort(int* data, int length, int start, int end){
if (start == end)
return;
int pivotIdx = Partition(data, length, start, end);
if (pivotIdx > start)
QuickSort(data, length, start, pivotIdx - 1);
if (pivotIdx < end)
QuickSort(data, length, pivotIdx + 1, end);
}
void QuickSortPort(int* data, int length){
if (data == nullptr || length <= 0)
return;
QuickSort(data, length, 0, length - 1);
}
//数组中出现次数超过一次的数字:
// 第一种方法:转化为查找数组中位数的问题,但不一定需要排序,只要使用快速查找第k个元素即可,
// 缺点:会修改输入数组
#include <stdlib.h>
#include <time.h>
int randomInRange(int start, int end){
srand((unsigned int)(time(NULL)));
if (start == end)
return start;
else if (start > end)
return end + rand() % (start - end + 1);
else
return start + rand() % (end - start + 1);
}
bool g_bIalidInput = false;
int Partition(int* data, int length, int start, int end){
if (data == nullptr || length<= 0 || start < 0 || end > length - 1){
g_bInvalidInput = true;
return 0;
}
int pivotIdx = randomInRange(start, end);
int pivot = data[pivotIdx];
std::swap(data[pivotIdx], data[end]);
int i = start - 1;
int j = end;
while (i <= end - 1 && j >= start){
while (data[++i] < pivot) {;}
while (data[--j] > pivot) {;}
if (i < j)
std::swap(data[i], data[j]);
else
break;
}
std::swap(data[i], data[end]);
return i;
}
bool CheckMoreThanHalf(int* data, int length, int result){
bool isConfirmed = true;
int count = 0;
for (int i = 0; i < length; ++i){
if (data[i] == result)
count++;
}
if (count*2 <= length)
isConfirmed = false;
return isConfirmed;
}
int FindMoreThanHalf(int* data, int length){
if (data == nullptr || length <= 0){
g_bIalidInput = true;
return 0;
}
int start = 0;
int end = length - 1;
int pivotIdx = Partition(data, length, start, end);
int middle = length >> 1;
while (pivotIdx != middle){
if (pivotIdx < middle)
pivotIdx = Partition(data, length, pivotIdx + 1, end);
else
pivotIdx = Partition(data, length, start, pivotIdx - 1);
}
int result = data[pivotIdx];
if (CheckMoreThanHalf(data, length, result))
return result;
else {
g_bInvalidInput = true;
return 0;
}
}
//数组中出现次数超过一半的数字:
// 第二种方法:出现超过一半的数字出现总次数超过其他所有数字次数,无需修改数组
bool g_bInvalidInput = false;
bool CheckMoreThanHalf(int* data, int length, int result){
bool isConfirmed = true;
int count = 0;
for (int i = 0; i < length; ++i){
if (data[i] == result)
count++;
}
if (count*2 <= length)
isConfirmed = false;
return isConfirmed;
}
int FindMoreThanHalf2(int* data, int length){
if (data == nullptr || length <= 0){
g_bInvalidInput = true;
return 0;
}
int number = data[0];
int count = 1;
for (int i = 1; i < length; ++i){
if (data[i] == number)
count++;
else if (count != 0)
count--;
else {
number = data[i];
count = 1;
}
}
if (CheckMoreThanHalf(data, length, number))
return number;
else {
g_bInvalidInput = true;
return 0;
}
}
// 找出最小的k个数:不要求排序
// 第一种方法:快速查找O(n)时间复杂度,利用快速排序思想,Partition函数,
#include <stdlib.h>
#include <time.h>
int randomInRange(int start, int end){
srand((unsigned int)(time(NULL)));
if (start == end)
return start;
else if (start > end)
return end + rand() % (start - end + 1);
else
return start + rand() % (end - start + 1);
}
bool g_bInvalidInput = false;
int Partition(int* data, int length, int start, int end){
if (data == nullptr || length<= 0 || start < 0 || end > length - 1){
g_bInvalidInput = true;
return 0;
}
int pivotIdx = randomInRange(start, end);
int pivot = data[pivotIdx];
std::swap(data[pivotIdx], data[end]);
int i = start - 1;
int j = end;
while (i <= end - 1 && j >= start){
while (data[++i] < pivot) {;}
while (data[--j] > pivot) {;}
if (i < j)
std::swap(data[i], data[j]);
else
break;
}
std::swap(data[i], data[end]);
return i;
}
void leastKNumbers(int* data, int length, int k){
if (data == nullptr || length <= 0 || k <= 0 || k > length)
return;
int start = 0;
int end = length - 1;
int pivotIdx = Partition(data, length, start, end);
while (pivotIdx != k - 1){
if (pivotIdx > k - 1)
pivotIdx = Partition(data, length, start, pivotIdx - 1);
else
pivotIdx = Partition(data, length, pivotIdx + 1, end);
}
for (int i = 0; i <= pivotIdx; ++i){
if (i == pivotIdx)
cout << data[i] << endl;
else
cout << data[i] << ' ';
}
}
//第二种方法:利用二叉树(红黑树),STL中的set和multiset都是基于红黑树实现的最大/最小堆,支持O(log k)时间的插入c.insert(x)/删除操作c.erase(x), O(1)时间查找最大值c.begin()
//时间复杂度:nlogk,不会修改输入数据, 不要求一次载入所有数据到内存,只要求内存存储k个数字的一个容器,一次读入一个数据;
// 适合海量数据处理,即n很大, k很小的数据
#include <set>
#include <vector>
using namespace std;
typedef std::multiset<int, greater<int>> intSet;
typedef std::multiset<int, greater<int>>::iterator setIterator;
void leastKNumbers(const vector<int>& data, intSet& leastKNumbers, int k){
leastKNumbers.clear();
vector<int>::const_iterator iter = data.begin();
for (; iter != data.end(); ++iter){
if (leastKNumbers.size() < k){
leastKNumbers.insert(*iter);
}
else {
setIterator greatestIter = leastKNumbers.begin();
if ((*iter) < (*greatestIter)){
leastKNumbers.erase(greatestIter);
leastKNumbers.insert(*iter);
}
}
}
}
intSet leastKNumbersPort(const vector<int>& data, int k){
if (data.size() > 0 && k > 0 && k <= data.size()){
intSet leastKSet;
leastKNumbers(data, leastKSet, k);
return leastKSet;
}
else
throw exception();
}
快速排序/快速查找(第k个, 前k个问题)的更多相关文章
- 输出前 k 大的数
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB 描述 给定一个数组,统计前k大的数并且把这k个数从大到小输出. 输入 第一行包含一个整数n,表示数组的大小 ...
- 算法导论学习之线性时间求第k小元素+堆思想求前k大元素
对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思 ...
- 求数组前K个大的数
我们举例,假若从10000万个数里选出前100个最大的数据. 首先我们先分析:既然要选出前100个最大的数据,我们就建立一个大小为100的堆(建堆时就按找最大堆的规则建立,即每一个根节点都大于它的子女 ...
- 原创:从海量数据中查找出前k个最小或最大值的算法(java)
现在有这么一道题目:要求从多个的数据中查找出前K个最小或最大值 分析:有多种方案可以实现.一.最容易想到的是先对数据快速排序,然后输出前k个数字. 二.先定义容量为k的数组,从源数据中取出前k个填 ...
- 快速查找无序数组中的第K大数?
1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高 ...
- 快速排序及查找第K个大的数。
本文提供了一种基于分治法思想的,查找第K个大的数,可以使得时间复杂地低于nlogn. 因为快排的平均时间复杂度为nlogn,但是快排是全部序列的排序, 本文查找第k大的数,则不必对整个序列进行排序.请 ...
- 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大
思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...
- 海量数据中找出前k大数(topk问题)
海量数据中找出前k大数(topk问题) 前两天面试3面学长问我的这个问题(想说TEG的3个面试学长都是好和蔼,希望能完成最后一面,各方面原因造成我无比想去鹅场的心已经按捺不住了),这个问题还是建立最小 ...
- MATLAB寻找数组前k个大值
有时候我们需要寻找数组的前k个大值并按照顺序输出, 在C语言可以通过快速排序等算法,快速求得,这里用matlab写了一个比较简单实用的程序(适用于数组长度不是特别大的情况). function [va ...
随机推荐
- python学习好文
摘要: 学习别人的学习历程. 一 iTech的博客 http://www.cnblogs.com/itech/archive/2011/01/31/1948265.html
- 创建自己的代码片段(CodeSnippet)
前言 工作中经常会写一些重复的代码片段,如自动属性.for循环.Action等等,针对这种情况,VisualStudio已经给我们提供了一个非常方便的功能--代码片段,是我们可以简单的输入几个字母就能 ...
- hadoop环境中误删除tmp文件夹的恢复
情景描述: 种种原因,不小心把系统根目录中的tmp文件删除了!发现jps之后看不到 master主机上面的namenode,resourcemanager,secondarynamenode三个进程了 ...
- ubuntu下升级网卡驱动
ubuntu下升级网卡驱动 无线局域网环境下,有个笔记本儿的无线经常断,而其它的终端都好好的,唯独它不行.所以想到检查和更新下无线网卡的驱动看看.以下是操作流程,记录一下. 阅读说明:##为标签, / ...
- 使用Hibernate模板调用存储过程
前提是该Dao类已经已经继承了org.springframework.orm.hibernate5.support.HibernateDaoSupport,并且在整个项目中已经配置好了事务,或者是手动 ...
- Git版本控制系统之基本使用
最早是通过接触著名的开源社区Github了解到Git的,但一直没有系统学习过.这次下定决心从头到尾系统的学一学,也将学习过程记录于此,供大家批驳.本篇文章先从以下几个方面简单了解一下Git: Git的 ...
- java垃圾回收过程
对于年轻代,刚开始创建的对象都是放置在eden区的,而将年轻代分成3个部分,主要是为了生命周期短的对象尽量留在年轻代.当eden区申请不到空间的时候,进行minorGC,把存活的对象拷贝到survio ...
- python--DenyHttp项目(2)--ACM监考服务器端
服务器端: #coding:utf-8 ''' ServerGui.py 设置比赛开始时间 设置比赛结束时间 若时间无误启动监听服务 ''' import time import re import ...
- mybatis 详解(六)------通过mapper接口加载映射文件
通过 mapper 接口加载映射文件,这对于后面 ssm三大框架 的整合是非常重要的.那么什么是通过 mapper 接口加载映射文件呢? 我们首先看以前的做法,在全局配置文件 mybatis-conf ...
- oracle-使用数据泵对不同用户和不同表空间的数据迁移
oracle-使用数据泵对不同用户和不同表空间的数据迁移 ---------------------------------------------------2013/11/13 expdp和imp ...