快速排序/快速查找(第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 ...
 
随机推荐
- Infer 在 Mac 上的安装和环境配置
			
Infer 在 Mac 上的安装和环境配置 Infer 介绍 Infer 是一个静态分析工具.Infer 可以分析 Objective-C, Java 或者 C 代码,报告潜在的问题. 任何人都可以使 ...
 - C++ STL pair详解
			
一.解释: p { margin-bottom: 0.25cm; direction: ltr; color: #00000a; line-height: 120%; text-align: left ...
 - 时间戳,取值问题  and  倒计时的前端处理
			
JavaScript 获取当前时间戳: 第一种方法: var timestamp = Date.parse(new Date()); 获取的时间戳是把毫秒改成000显示, 结果:12809773300 ...
 - phpstudy命令行中数据表插入中文显示不了的问题
			
在PHPstudy环境下,做MySQL操作,往数据表里面插入数据的时候,如果是中文的数据就会显示不了或者是问号?. 这个问题搞了我一晚上了,终于知道问题所在. 下载的PHPstudy的MySQL数据库 ...
 - SecureCRT 常用命令大全
			
常用命令:一.ls 只列出文件名 (相当于dir,dir也可以使用) -A:列出所有文件,包含隐藏文件. -l:列表形式,包含文件的绝大部分属性. -R:递归显示. --help:此命令的帮助. 二. ...
 - 百分比相对计算注意事项CSS3
			
百分比计算 1.涉及元素定位,和大小计算,基于元素自身的包含块. 2.元素背景图的大小计算,位置计算,基于元素自身的宽,高. 2.元素图片边框使用的图图片大小计算,基于元素自身的宽,高.
 - css小随笔
			
一.什么是CSS W3C标准中,倡导有3:其一为内容与表现分离,其二为内容与行为分离,其三为内容结构的语义化.其倡导中第一条的"表现"指的便可以说是CSS.CSS全称Cascadi ...
 - java实现网页爬虫
			
接着上面一篇对爬虫需要的java知识,这一篇目的就是在于网页爬虫的实现,对数据的获取,以便分析. -----> 目录: 1.爬虫原理 2.本地文件数据提取及分析 3.单网页数据的读取 4.运 ...
 - 一个普通的 Zepto 源码分析(一) - ie 与 form 模块
			
一个普通的 Zepto 源码分析(一) - ie 与 form 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核 ...
 - Java入门——(4)多线程
			
关键词:线程.Thread.Runnable.sleep().yield().join().同步 一.线程的概述 在一个操作系统中,每个独立执行的程序都可以称为一个进程,也就是"正在 ...