问题描述:给定一系列数{a1,a2,...,an},这些数无序的,现在求第k大的数。

看到这个问题,首先想到的是先排序,然后直接输出第k大的数,于是得到啦基于排序的算法

算法一:

#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a, int b){ return a > b; }
int main(){
int k;
int a[9] = { 6, 5, 9, 8, 2, 1, 7, 3, 4 };
cout << "Input k:";
cin >> k;
sort(a, a + 9, cmp);
cout << a[k - 1] << endl;
return 0;
}

算法耗时主要在排序上,于是这个算法复杂度是O(nlogn);

算法二:

算法二是基于分解的方法,问题求解的是第k大的数,若果我将这系列数全部排序肯定会做太多无用功,比如我只需找出第k大,我可以先找出1大,第2大....第k大,在结束,此时时间为O(kn),当k比较少时候算法复杂度为0(n),若当k是关于n的函数时候算法复杂度为O(n2),最好的情况是k=1和k=n,最坏的情况是k=n/2,O(n)=<f(n)<=O(n2/2);具体代码如下:

#include<iostream>
using namespace std;
#include<cmath>
#define m int(pow(-2,31)); /*将m赋值为最小的整数*/
int Find_Kth(int a[], int n, int k);
int main(){
int k;
int a[9] = { 6, 5, 9, 8, 2, 1, 7, 3, 4 };
cout << "Input k:";
while (cin >> k){
cout << Find_Kth(a, 9, k) << endl;
}
return 0;
}
int Find_Kth(int a[], int n, int k){
int i,j, redex=0, NewMax = a[0];
for (i = 0; i < k; i++){ /*每次采用打擂台方法找到本次最大值后赋值为m*/
for (i = 0; i < n; i++)
if (a[i]>NewMax){
NewMax = a[i];
redex = i;
}
a[redex] = m;
}
return NewMax;
}

算法二有局限性,复杂度取决于k值,下面还是采用基于分解的思想,我们需要的是求第k大的数,于是可以采用快速排序的思想,任意选择一个数key将这序列数分解为s1和s2两个序列,其中s1中的数全部小于key,而s2中的数全部大于或等于key(key是s2中的最小的数),设s1和s2中元素个数为|s1|和|s2|,如果k==|s2|,那摩说明第k大的数恰好为key,如果k<|s2|,那么问题转化为求|s2|中第k大的数,如果k>|s2|,那么问题转化为求s1中第k-|s2|大的数,这样所有的过程可以通过递归来实现,于是有啦算法三。

算法三:
#include<iostream>
using namespace std;
int Find_Kth(int *a,int left,int right,int k);
int main(){
int k;
int a[9] = {6,5,9,8,2,1,7,3,4};
cout << "Input k:";
cin >> k;
cout << Find_Kth(a, 0, 8, k) << endl; /*输出第k大的数*/
return 0;
}
int Find_Kth(int *a,int left,int right, int k){
int key = a[left]; /*设定关键值*/
int low = left,high=right;
while (high>low){ /*类似于快速排序*/
while (a[high] >= key&&high>low)
high--;
a[low] = a[high];
while (a[low] <= key&&high>low)
a[low++];
a[high] = a[low];
}/*循环跳出必定有high=low*/
a[low] = key;
int r = right - low + 1; /*右端元素个数*/
if (k== r)
return a[low]; //恰好a[low]为第k大值
else if (k < r)
return Find_Kth(a, low+1, right, k); //第k大的值在a[low]右边第k大值
else
return Find_Kth(a, left, low - 1, k - r); /*第k大值在a[low]右边序列的第r-k大的值*/
}

事实上,C++的STl早已经为我们提供啦函数nth_element,包含头文件#include<iostream>中.nth_element有四个参数,第一个和第三个为begin和end的地址,表示搜索范围是区间[begin,end)里面的数,第二个参数为找的第k个数的地址,第四个参数为cmp函数,函数可以看成 void element(int*begin,int*Nth,int*end,boo(*pdrf)(int a,int b));

#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a, int b){
return a > b;
}
int main(){
int k;
int a[9] = { 6, 5, 9, 8, 2, 1, 7, 3, 4 };
cout << "Input k:";
while (cin >> k){
nth_element(a, a + k-1,a+9, cmp); //将第k大的数放在k-1位置
cout << a[k - 1] << endl;
}
return 0;
}

寻找数列中第k大的数算法分析的更多相关文章

  1. [经典算法题]寻找数组中第K大的数的方法总结

    [经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26   字体:[大 中 小] 打印复制链接我要评论   今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...

  2. 求数列中第K大的数

    原创 利用到快速排序的思想,快速排序思想:https://www.cnblogs.com/chiweiming/p/9188984.html array代表存放数列的数组,K代表第K大的数,mid代表 ...

  3. 寻找数组中第K大的数

    给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...

  4. 查找数组中第k大的数

    问题:  查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...

  5. 找出整数中第k大的数

    一  问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二  举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...

  6. 找出N个无序数中第K大的数

    使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求 时间复杂度: 1.若随机选取枢纽,线性期望时间O(N) 2.若 ...

  7. 乱序数组中第k大的数(顺序统计量)

    该问题是顺序统计量中十分经典的问题. 使用快排中的分区法,将第k大的数排序.若双向扫描分区加上三点中值法或绝对中值法,可以保证在 O(n) 时间里找出第k大的数. 补充:可以直接使用C++STL中的n ...

  8. 查找无序数组中第K大的数

    思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...

  9. 4. Median of Two Sorted Arrays *HARD* -- 查找两个排序数组的中位数(寻找两个排序数组中第k大的数)

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

随机推荐

  1. WPF 三态按钮(PNG贴图)

    原文 http://blog.csdn.net/power_YQ/article/details/7177183 <Window.Resources> Style x:Key=" ...

  2. 读配置文件 properties

    /** * */package com.sprucetec.tms.fee.utils;import java.io.IOException;import java.util.ArrayList;im ...

  3. C语言入门(14)——结构体

    整数.字符.布尔值.浮点数这些数据类型都具有单一的值,这些可称为基本数据类型.但字符串是一个例外,它由很多字符组成,像这种由基本类型组成的数据类型称为复合数据类型,正如表达式和语句有组合规则一样,由基 ...

  4. HDU 5738 Eureka(极角排序)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5738 [题目大意] 给出平面中一些点,在同一直线的点可以划分为一个集合,问可以组成多少包含元素不少 ...

  5. poj2840

    #include <stdio.h> #include <stdlib.h> #include<string.h> int main() { int n,len; ...

  6. http://docs.aliyun.com/#/rds/best-practices/collocation&security

    http://docs.aliyun.com/#/rds/best-practices/collocation&security

  7. CSS实现宽高成比例缩放

    用js实现一个宽度自适应,高度随着宽度变化而变化的矩形,相信大家肯定都会.无非是js获取一下元素宽度,然后再计算出相应比例的高度,然后赋给元素,但如果要求只用CSS实现呢.         html代 ...

  8. Android Popupwindow 拖动

    版本号:1.0 日期:2014.4.29 版权:© 2014 kince 转载注明出处 关于View的拖动大家应该比較了解了,比方对一个控件IamgeView拖动,或者一个视图View拖动,实现方式也 ...

  9. go-vim配置

    一.环境准备: 系统环境说明: [root@docker golang]# cat /etc/redhat-release CentOS Linux release (Core) [root@dock ...

  10. JavaScript之apply()和call()的区别

    我 在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示 例,总算是看的有点眉目了,在这里我做如下笔记,希望和 ...