快速排序/快速查找(第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 ...
随机推荐
- HTML5 开发APP(头部和底部选项卡)
我们开发app有一定固定的样式,比如头部和底部选项卡部分就是公共部分就比如我在做的app进来的主页面就像图片显示的那样 我们该怎么实现呢,实现我们应该建一个主页面index.html,然后建五个子页面 ...
- Docker Registry
前言 上一篇文章讲了Docker Machine实现多主机Docker节点的管理.本文讲解如何实现Docker Registry,其实这个在第一篇Docker入门一文中已经简单介绍,本文仅是对一些细节 ...
- Xamarin.Forms(二) 返回页面的数据刷新
这几天在做一个课程表的小程序,遇到了这样一个问题: app打开便是课程表的页面,如果课程表页面没有数据的话需要跳转到同步课表页面模拟登陆教务管理系统获取课表,并显示在课程表页面,这样就需要从同步课表页 ...
- c++ STL 容器——序列
STL中11个容器类型分别是deque,list,queue,priority_queue,stack,vector,map,multimap,set,multiset,bieset(在比特级处理数据 ...
- IIS下防止mdb数据库被下载的实现方法
第一种方法:要求网站管理人员具体asp编程经验.因为现在的销售虚拟主机的系统,已经为用户建立了一个database目录,跟web目录同一个级别,用户访问的是web中的文件,而无法访问database目 ...
- Appium入门示例(Java)
一.使用Eclipse直接创建案例工程 1.打开Eclipse,[File]-->[New]-->[Project] 2.选择[Java Project]-->[Next] 3.输入 ...
- Exceptionless 本地部署踩坑记录
仅已此文记录 Exceptionless 本地部署所遇到的问题 1.安装ElasticSearch文本 执行elasticsearch目录中的elasticsearch.bat 没有执行成功. 使用命 ...
- 【NO.5】jmeter-结果文件
Jmeter的结果文件可以保存很多内容,你需要看哪个就勾选哪个,很简单是吧. 结果文件可以保存为2种形式:XML或者CSV.我印象里在书上提到过,如果保存为XML形式的结果文件,后续可以转化为表格便于 ...
- 从MySQL随机选取数据
--从MySQL随机选取数据 -------------------------2014/06/23 从MySQL随机选取数据最简单的办法就是使用”ORDER BY RAND()”; 方案一: SEL ...
- 最大流&流分布&不确定图网络可靠性
最大流:确定图上每条边含有可以传递的容量值,找到s-t之间可以传送最大的流值. 流分布:最大流是个值,假设极为f,我们要从s到t传递f的流量,对应了多个方案,每个方案就是一个流分布. 不确定图:不确定 ...