类快排算法

leetcode215

由于只要求找出第k大的数,没必要将数组中所有值都排序。

典型解法:快速排序分组。

在数组中找到第k大的元素
取基准元素,将元素分为两个集合,一个集合元素比基准小,另一个比基准大 ,三种情况。
1.比基准大的元素数目标志位m正好为k-1,基准就是目的元素。
2.比基准大的元素标志位m小于k, 那么就在比基准小的集合里面找第(k-m)大的元素
3.若是比基准大的元素为m大于k,那就继续在该集合里面找第k大的元素。

快排中的partition算法,返回key在数组中的位置的cnt(相对于left的偏移量),如果cnt正好等于k,那么问题则得到解决;如果cnt小于k,去左边找第k个;如果cnt>k,则去右边找第k-cnt个。直到key的位置等于k-1,则找对问题的解。

/*快排中的划分算法*/
int partition(int* input, int low, int high){int tmp = input[low]; // 取一个基准元素while (low < high) {while (low < high && input[high] <= tmp) {high--;}input[low] = input[high];while (low < high && input[low] >= tmp) {low++;}input[high] = input[low];}input[low] = tmp;return low;
}// 参数left需要小于right
int findK(int* array, int left, int right, int k) {//printf("%d %d %d\n", left, right, k);int i = partition(array, left, right);int cnt = i - left + 1;if (k == cnt) {return array[i];} else if (k < cnt) {return findK(array, left, i - 1, k);} else if (k > cnt) {return findK(array, i + 1, right, k-cnt);}return 0;
}

此解法的时间复杂度为O(N*lgK),logK次每次O(N),优于排序解法.

测试程序:

#include <iostream>
#include <vector>
using namespace std;/*快排中的划分算法*/
int partition(int* input, int low, int high)
{int tmp = input[low]; // 取一个基准元素while (low < high) {while (low < high && input[high] <= tmp) {high--;}input[low] = input[high];while (low < high && input[low] >= tmp) {low++;}input[high] = input[low];}input[low] = tmp;return low;
}// 这里得到的是第k小,自己n-k转换下即可, 或者改下划分函数
int findK(int* array, int left, int right, int k) {//printf("%d %d %d\n", left, right, k);int i = partition(array, left, right);int cnt = i - left + 1;if (k == cnt) {return array[i];}else if (k < cnt) {return findK(array, left, i - 1, k);}else if (k > cnt) {return findK(array, i + 1, right, k - cnt);}return 0;
}int main()
{vector<int> ilist = {9, 5, 8, 7, 3, 6, 2, 1, 4, 0};int arr[10];int n = ilist.size();std::copy(ilist.begin(), ilist.end(), arr);int k = 3;int num = findK(arr, 0, n-1, k);cout << num << endl;system("pause");return 0;
}

快排加二分查找:

int a[]={7,9,8,5,6,3,2,4,1,0};
const int K=6;
//解题思路就是利用快速排序,如果得到快速排序一次中间结果之后其所在位置即在
int QSort(int* a,int low,int high)
{if(low<high){int start=low,end=high;int key=a[start];while(start<end){while(start<end&&a[end]<key){end--;}a[start]=a[end];while(start<end&&a[start]>key){start++;}a[end]=a[start];            }a[start]=key;return start;}return -1;
}
int main()
{int start=0,end=sizeof(a)/sizeof(int)-1;int index=-2;while(index+1!=K){index=QSort(a,start,end);if(index<K){start=index+1;}else if(index>K){end=index-1;            }}cout<<a[index]<<"即为所求\n";
}

最小堆解法

构造一个大小为k的最小堆,堆中根节点为最小值。如果数组中最大的几个数均在堆中,那么堆中根节点的值就是问题的解。

可以用STL中的优先队列实现,因为优先队列的内部就是最大堆/最小堆实现的。

此解法的时间复杂度O(NlogK),N次logK。但是相比与类快速排序算法,需要额外的存储空间。

#include <iostream>
#include <vector>
using namespace std;void maxHeapify(int* array, int size, int i) {int left = 2 * i + 1;int right = 2 * i + 2;int small = i;if (left < size) {if (array[small] > array[left]) {small = left;}}if (right < size) {if (array[small] > array[right]) {small = right;}}if (small != i) {int temp = array[small];array[small] = array[i];array[i] = temp;maxHeapify(array, size, small);}
}void buildHeap(int* array, int size) {for (int i = size - 1; i >= 0; i--) {maxHeapify(array, size, i);}
}int findKByHeap(int* array, int n, int k) {buildHeap(array, k);for (int i = k; i < n; i++) {if (array[i] > array[0]) {int temp = array[i];array[i] = array[0];array[0] = temp;maxHeapify(array, k, 0);}}return array[0];
}int main()
{vector<int> ilist = {9, 5, 8, 7, 3, 6, 2, 1, 4, 0};int arr[10];int n = ilist.size();std::copy(ilist.begin(), ilist.end(), arr);int k = 5;int num = findKByHeap(arr, n, k);cout << num << endl;   system("pause");return 0;
}

参考博客:寻找第k大的数

其他可学习参考:[LeetCode]215 数组第k大的数

在无序数组中找到第k大的数

【算法】在N个乱序数字中查找第K大的数字

如何寻找无序数组中的第K大元素?

从无序数组中找出第K大的数

无序数组中找第K大的数相关推荐

  1. 【LeetCode】快排-无序整数数组中找第k大的数(或者最小的k个数)

    一个有代表性的题目:无序整数数组中找第k大的数,对快排进行优化. 这里先不说这个题目怎么解答,先仔细回顾回顾快排,掰开了揉碎了理解理解这个排序算法:时间复杂度.空间复杂度:什么情况下是复杂度最高的情况 ...

  2. 两个排序数组中找第k大的数

    一.题目描述 给定两个已经排序好的数组,找到两者所有元素中第k大的元素 二.解法分析 解法一:参照归并排序 将两个有序数组变成一个有序数组:merge两个数组,然后求第k大的数,时间复杂度O(m+n) ...

  3. 如何寻找无序数组中的第K大元素?

    如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...

  4. 【算法】快速选择算法 ( 数组中找第 K 大元素 )

    算法 系列博客 [算法]刷题范围建议 和 代码规范 [算法]复杂度理论 ( 时间复杂度 ) [字符串]最长回文子串 ( 蛮力算法 ) [字符串]最长回文子串 ( 中心线枚举算法 ) [字符串]最长回文 ...

  5. python:无序数组中寻找第K大的元素

    题目: 所谓"第(前)k大数问题"指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题. 解法1:堆排序 采用元素下沉法,维护一个k大小的最小堆, ...

  6. 找出无序数组中最小的k个数(top k问题)

    2019独角兽企业重金招聘Python工程师标准>>> 给定一个无序的整型数组arr,找到其中最小的k个数 该题是互联网面试中十分高频的一道题,如果用普通的排序算法,排序之后自然可以 ...

  7. 1985. 找出数组中的第 K 大整数

    1985. 找出数组中的第 K 大整数 给你一个字符串数组 nums 和一个整数 k .nums 中的每个字符串都表示一个不含前导零的整数. 返回 nums 中表示第 k 大整数的字符串. 注意:重复 ...

  8. 数组中的第K大元素问题(C++)

    数组中的第K大元素问题 问题: 在未排序的数组中找到第 k 个最大的元素.请注意,需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 约定: 假设这里数组的长度为 n. 方法一: ...

  9. 快速查找无序数组中的第K大数?

    1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高 ...

最新文章

  1. mysql tomcat 自动重连_基于tomcat+mysql的c/s模式下的系统自动更新
  2. 剑指offer——变态跳台阶
  3. Verilog功能模块——降采样
  4. 【华为云踩坑】开启了入方向规则的 tcp/80 端口,仍然无法访问
  5. OpenCASCADE:Foundation Classes简介
  6. Jenkins的关闭、重启
  7. why jQuery.clone does not work as expected
  8. coreldraw x4怎么会蓝屏_CorelDRAW广告条幅批量制作插件
  9. 信息学奥赛一本通(1403:素数对)
  10. fastdfs-启动服务-上传文件-连接问题
  11. python switch语句的多种实现方法
  12. Eclipse超级完美汉化教程
  13. TDateTime转
  14. 常用的js正则表达式
  15. linux终端输入五笔命令,Ubuntu 16.04如何安装Fcitx五笔拼音输入法
  16. 路由器上下行测试软件,无线传输性能测试平台和测试方法
  17. slk文件转换器安卓版_CoolUtils Total Excel Converter下载
  18. 测试计划报告---5W1H
  19. 公考之申论话题分析——基于词云和主题聚类
  20. 验证“哥德巴赫猜想”

热门文章

  1. 海思Hi3518e烧录步骤
  2. 【STM32-V5】STM32F407开发板开源, 丰富软件资源, 强劲硬件配置, 配套600实例, 20套手册带视频教程2023-05-15
  3. js中(双感叹号)符号的用法解读
  4. 垃圾收集器与内存分配策略
  5. win10 计算机休眠后无法唤醒,Win10系统进入睡眠后无法唤醒的解决方法
  6. 手动证书管理与自动证书管理
  7. 我的2017年文章汇总——Java并发篇
  8. 今日报错系列:未定义的SYSTEMTIME
  9. 如何向phpMyAdmin中批量导入excel表格数据
  10. 张维迎,你语不惊人死不休啊