输出数组第k大的元素

用快速排序的思想输出数组第k大的元素:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4
 5 //递归实现:返回数组第k大的值.数组下标区间是[begin,end].其中数组假定n个元素,则k的值在区间[1,n].
 6 //能够使用这种方法的前提条件是:n个数不能重复。如果n个数中有重复,那么区间的大小不能保证就是第K大。
 7 int findkth(int* arr, int begin, int end, int k)
 8 {
 9     int key=arr[begin];
10     int i=begin,j=end;
11     while(i<j)
12     {
13         while(i<j && arr[j]<=key) j--;
14         arr[i]=arr[j];
15         while(i<j && arr[i]>=key) i++;
16         arr[j]=arr[i];
17     }
18     arr[i]=key;
19
20     //递归的结束条件为某一记录刚好划分到第k个位置
21     //由于数组从0开始,所以需要加1了
22     if (i == k-1)return arr[i];
23     else if (i < k-1) return findkth(arr, i+1, end, k);
24     else return findkth(arr, begin, i-1, k);
25 }
26
27
28 //只做了一轮划分,没有递归完成快速排序.返回的是划分的下标。数组a[]下标区间[low,high]
29 template <class T>
30 int partition(T a[],int low,int high)
31 {
32     T key=a[low];
33     int i=low,j=high;
34     while(i<j)
35     {
36         while(i<j && a[j]>=key) j--;
37         a[i]=a[j];
38         while(i<j && a[i]<=key) i++;
39         a[j]=a[i];
40     }
41     a[i]=key;
42     return i;
43 }
44
45 //利用快速排序的思想查找第K大的数值
46 //第一个参数代表要查找的数组
47 //第二个参数代表数组的长度
48 //第三个参数代表要查找第几大的元素
49 //非递归
50 template <class T>
51 T findkth2(T a[],int n,int k)
52 {
53     int low=0,high=n-1;
54     while(1)
55     {
56         int pos=partition(a,low,high);
57         if(pos==n-k) return a[pos];
58         else if(pos<n-k)
59         {
60             low=pos+1;
61             high=n-1;
62         }
63         else if(pos>n-k)
64         {
65             high=pos-1;
66             low=0;
67         }
68     }
69 }
70
71 int main()
72 {
73     int a[11]={78934,234,65,32,543,354,567,3412,23,547,423};
74     int b[11]={78934,234,65,32,543,354,567,3412,23,547,423};
75     int c[11]={78934,234,65,32,543,354,567,3412,23,547,423};
76
77     for(int i=0;i<11;i++) cout<<a[i]<<" ";
78     cout<<endl;
79     sort(a,a+11);
80     for(int i=0;i<11;i++) cout<<a[i]<<" ";
81     cout<<endl;
82
83     for(int i=11;i>=1;i--)
84         cout<<findkth(b,0,10,i)<<" ";
85     cout<<endl;
86
87     for(int i=11;i>=1;i--)
88         cout<<findkth2(c,11,i)<<" ";
89     cout<<endl;
90
91
92     cout<<endl<<endl;
93     for(int i=0;i<11;i++) cout<<b[i]<<" ";
94     cout<<endl;
95     for(int i=0;i<11;i++) cout<<c[i]<<" ";
96     cout<<endl;
97     return 0;
98 }  

参考:http://blog.csdn.net/guangwen_lv/article/details/39674241

利用快速排序的特点:第一遍排序会确定一个数的位置,这个数左边都比它大,右边都比他小(降序),当左边区间大于K时,说明我们求的第K大数在左边区间,这时我们可以舍弃右边区间,将范围缩小到左边区间从而重复上述过程,直到确定一个数的位置时,左边区间的小是K-1那么这个数字就是我们所求。右边同理。

能够使用这种方法的前提条件是:n个数不能重复。如果n个数中有重复,那么区间的大小不能保证就是第K大。可以用HASH判重来将重复的数据去掉。然后再使用上述方法。

也可阅读如下另一位网友的java代码:

 1 /** * Created with IntelliJ IDEA.
 2 * User: hqtc
 3 * Date: 16-3-22
 4 * Time: 下午9:52
 5 * To change this template use File | Settings | File Templates.
 6 */
 7 public class QuickSort{
 8
 9     private int getSeparatorIndex(int[] nums, int low, int high) {
10         int k = nums[low];
11         while (low < high) {
12             while (k < nums[high] && low < high) {
13                 high--;
14             }
15             if (low < high)
16                 nums[low++] = nums[high];
17             while (k > nums[low] && low < high) {
18                 low++;
19             }
20             if (low < high)
21                 nums[high--] = nums[low];
22         }
23         nums[low] = k;
24         return low;
25     }
26
27     public void sort(int num[], int low, int high) {
28         if (low < high) {
29             int sepIndex = getSeparatorIndex(num, low, high);
30             sort(num, low, sepIndex - 1);
31             sort(num, sepIndex + 1, high);
32         }
33     }
34
35     public int findKthMax(int arr[], int k, int left, int right) {
36         int sepIndex = getSeparatorIndex(arr, left, right);
37         if (k == arr.length - sepIndex) {
38             return arr[sepIndex];
39         } else {
40             if (k > arr.length - sepIndex) {
41                 return findKthMax(arr, k, left, sepIndex - 1);
42             } else {
43                 return findKthMax(arr, k, sepIndex + 1, right);
44             }
45         }
46     }
47 }
48
49 /*作者:环球探测
50 链接:http://www.jianshu.com/p/9f887dfc374a
51 來源:简书
52 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
时间: 2024-10-13 21:47:24

输出数组第k大的元素的相关文章

寻找数组中的第K大的元素,多种解法以及分析

遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因为不要求别的信息只要计算出第K大的元素.当然,如果在某种情况下需要频繁访问第K大的元素就可以先进行一次排序在直接得出结果. 第一种方式是这样,用选择排序,冒泡法,或者交换排序这类的排序,对前K个元素进行排序.这三种算法也许不是最快的排序算法.但是都有个性质:计算出最大(小)的元素的算法复杂度是O(N

数组中第K大的元素

数组中第K大的元素总结 解法1: 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k). 解法2: 如果k很小,比如第五个最大的数,而整个数组的长度非常的大,那么,还有一种方法就是,我做k遍找最大的数,每做一遍,就把最大的放在数组的最后面(遍历一次找出最大的数例如冒泡,选择排序都可以.),然后减少数组扫描的范围,就可以把第k大的数找出来,这样做的复杂度就是O(K*N),在K很小的情况下,还是不错的. 解法3: 利用快速排序的思想,从数组S中随机找

hrbust 1840 (树状数组第k大) 删点使用

小橙子 Time Limit: 2000 MS Memory Limit: 32768 K Total Submit: 2(2 users) Total Accepted: 1(1 users) Rating:  Special Judge: No Description 玻璃小屋里曾经住着一个小橙子.小橙子小小的,性格很直.直性子的小橙子傻乎乎的,还很爱看火影.海贼王什么的.他收藏了很多动画片的光碟,光碟太多了,他打算整理一下. 他口中念念有词:“这个,插入第三个光碟前面,这个,插入第五个光碟

算法:寻找数组的第二大的元素(不排序、只循环一次)

该算法的原理是,在遍历数组的时,始终记录当前最大的元素和第二大的元素.示例代码: package demo01 import ( "fmt" ) func NumberTestBase() { fmt.Println("This is NumberTestBase") nums := []int{12, 24, 2, 5, 13, 8, 7} fmt.Println("nums:", nums) secondMax := getSecondMax

(算法)Partition方法求数组第k大的数

如题,下面直接贴出代码: #include <iostream> using namespace std; int Partition(int* A,int left,int right){ int key=A[left]; while(left<right){ while(left<right && A[right]>=key) right--; if(left<right) A[left]=A[right]; while(left<right

利用堆排序找出数组中前n大的元素

#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <time.h> #define MAX_SIZE 400001 #define PARENT(i) (i/2) #define RIGHT(i) (i*2 + 1) #define LEFT(i) (i*2) #define EXCHANGE(a,b,t) do{t=a;a=b;b=t;}while(0) // 生成不重复

有序数组寻找中位数以及寻找K大元素

问题描述: 两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n)).转化成找到两个数组的第K大数字进行解决 解题方法: 对于一个长度为n的已排序数列a,若n为奇数,中位数为a[n / 2 + 1] , 若n为偶数,则中位数(a[n / 2] + a[n / 2 + 1]) / 2如果我们可以在两个数列中求出第K小的元素,便可以解决该问题不妨设数列A元素个数为n,数列B元素个数为m,各自升序排序,求第k小元素取A[k / 2] B[k / 2]

1540: 第k大数 两个数组元素相乘后的第k大( 二分答案 + 输入输出优化 )

1540: 第k大数 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 104 Solved: 6 [Submit][Status][Web Board] Description 有两个序列a,b,它们的长度分别为n和m,那么将两个序列中的元素对应相乘后得到的n*m个元素从大到小排列后的第k个元素是什么? Input 输入的第一行为一个正整数T (T<=10),代表一共有T组测试数据. 每组测试数据的第一行有三个正整数n,m和k(1<=n, m&l

Coursera Algorithms week3 快速排序 练习测验: Selection in two sorted arrays(从两个有序数组中寻找第K大元素)

题目原文 Selection in two sorted arrays. Given two sorted arrays a[] and b[], of sizes n1 and n2, respectively, design an algorithm to find the kth largest key. The order  of growth of the worst case running time of your algorithm should be logn, where n