快速排序/快速查找(第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 ...
随机推荐
- 再起航,我的学习笔记之JavaScript设计模式01
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 在通 ...
- RabbitMQ 使用场景一
安装环境 1.下载安装 Erlang 运行时环境 2.下载安装 RabbitMQ Server 应用程序 3.启动 RabbitMQ 服务(默认启动) 4.安装管理平台插件并打开远程访问权限 4.1. ...
- 纯Css绘制三角形箭头三种方法
在制作网页的过程中少不了绘制类似图片的三角形箭头效果,虽然工程量不大,但是确实麻烦.在学习的过程中,总结了以下三种方法,以及相关的例子. 一.三种绘制三角形箭头方法 1.方法一:利用overflow: ...
- mybatis 详解(八)------ 懒加载
本章我们讲如何通过懒加载来提高mybatis的查询效率. 本章所有代码:http://pan.baidu.com/s/1o8p2Drs 密码:trd6 1.需求:查询订单信息,有时候需要关联查出用户信 ...
- Linux操作系统-命令-vmstat
叨叨两句 涉及监控服务器性能的命令,除了有vmstat之外,还有top.iostat.netstat.本文只是介绍一下这4个命令中的1个.剩下的3个命令可以参考以下网上的资料就差不多能会了. 推荐to ...
- Linux - 简明Shell编程13 - 用户输入(UserInput)
脚本地址 https://github.com/anliven/L-Shell/tree/master/Shell-Basics 示例脚本及注释 1 - arguments #!/bin/bash i ...
- python 导入模块 import 理解
--python 导入模块 import 理解 -----------------------------------2014/03/18 python 导入一个模块的过程要求有一个叫做“路径搜索”的 ...
- 理解LGWR,Log File Sync Waits以及Commit的性能问题[转]
理解LGWR,Log File Sync Waits以及Commit的性能问题 一.概要: 1. Commit和log filesync的工作机制 2. 为什么log file wait太久 3. ...
- mac监听Dock激活程序
mac监听Dock激活程序 涉及库添加: LIBS += -framework CoreFoundation -framework Carbon -lobjc 涉及头文件: #include < ...
- leetcode——262. Trips and Users
The Trips table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are b ...