乱序中找k大
来源:互联网 发布:日语网络考试 编辑:程序博客网 时间:2024/05/20 02:25
求一个数组中第k大的数,我第一印象是冒泡,因为只要冒泡k趟即可,第一趟冒泡第一大,第二次冒泡第二大,第k次冒泡第k大,时间复杂度为O(kn),n为数组长度。但是我们都知道快速排序是对冒泡的改进,降低冒泡的递归深度,使时间复杂度降低到O(nlgn),为什么不用快排呢?那么快排的时间复杂度又是多少呢?
因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。
最差情况如下:假设快排每次都平均划分,但是都不在枢纽元素上找到第k大
第一趟快排没找到,时间复杂度为O(n),第二趟也没找到,时间复杂度为O(n/2),。。。。。,第k趟找到,时间复杂度为O(n/2k),所以总的时间复杂度为
O(n(1+1/2+….+1/2k))=O(n),明显比冒泡快,虽然递归深度是一样的,但是每一趟时间复杂度降低。
这段来自:http://www.cnblogs.com/GODYCA/archive/2013/01/02/2842297.html
好了,接下来附上我的代码,原文的快排代码和我的有点不一样:
#include <iostream>using namespace std;#define SWAP(x, y) {int t; t=x; x=y; y=t;}#define length(array) sizeof(array)/sizeof(array[0])int quicksort(int *array, int left, int right){ int res = 0; if (left < right){ int temp = array[left]; int i = left + 1; int j = right; while (1){ while ((i < right) && (array[i] < temp)){ i++; } while ((j > left) && (array[j] > temp)){ j--; } if (i >= j){ res = j; break; } /* swap为什么不传地址呢,因为是宏,不是函数,这个函数会展开成语句 */ SWAP(array[i], array[j]); i++; j--; } SWAP(array[j], array[left]); } return res;}int QuickSort_K_MAX(int *a, int low, int high, int k){ if (low >= high) return a[low]; else { int mid = quicksort(a, low, high); //划分子递归数组 if (mid > k) QuickSort_K_MAX(a, low, mid - 1, k); //左递归 else if (mid < k) QuickSort_K_MAX(a, mid + 1, high, k); //右递归,一旦右递归mid+1=high,将退化成冒泡,递归深度将变成n,n为数组长度 else return a[mid]; }}int main(){ int a[10] = { 10, 7, 8, 6, 3, 1, 5, 2, 4, 9 }; int k = 6; int len = length(a); printf("%d", QuickSort_K_MAX(a, 0, len - 1, k-1)); return 0;}
代码中,我求k=6,即求第6大,然后传的是k-1,因为索引时0开始的嘛,第6大索引为5。
然后就找到了6。
0 0
- 乱序中找k大
- P1788第k大
- 找第k大
- 第K大素数
- 数列第k大
- 区间第K大
- 第K大素数
- K大的 数
- 第k大元素
- 寻找第K大
- 第k大元素
- P1788 第k大
- 寻找第K大
- [JZOJ4927]第K大
- JZOJ4927. 第K大
- 第K大
- 快排求第k大
- 求第k大
- ios学习视频
- 字符串中找出所有数字串,并将其存放到集合当中!
- 欢迎使用CSDN-markdown编辑器
- c#基础语言编程-Path和Directory
- 常用 U-boot命令详解
- 乱序中找k大
- 移植Bluez-4.1
- nagios安装.配置与监控的整个过程
- 看数据结构写代码(25) 二叉链表 求 宽度,交换左右子树,判断完全二叉树,求节点祖先
- 《C++语言基础》程序阅读——构造函数和析构函数
- Vistual Studio 2010 第二天
- 笔记本升级ssd固态硬盘,如何知道主板SATA接口是SATA 2.0还是SATA 3.0?
- Spring AOP原理及拦截器
- 算法导论—堆排序C++实现