寻找数列中第k大的数算法分析
问题描述:给定一系列数{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大的数算法分析的更多相关文章
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- 求数列中第K大的数
原创 利用到快速排序的思想,快速排序思想:https://www.cnblogs.com/chiweiming/p/9188984.html array代表存放数列的数组,K代表第K大的数,mid代表 ...
- 寻找数组中第K大的数
给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...
- 查找数组中第k大的数
问题: 查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...
- 找出整数中第k大的数
一 问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二 举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...
- 找出N个无序数中第K大的数
使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求 时间复杂度: 1.若随机选取枢纽,线性期望时间O(N) 2.若 ...
- 乱序数组中第k大的数(顺序统计量)
该问题是顺序统计量中十分经典的问题. 使用快排中的分区法,将第k大的数排序.若双向扫描分区加上三点中值法或绝对中值法,可以保证在 O(n) 时间里找出第k大的数. 补充:可以直接使用C++STL中的n ...
- 查找无序数组中第K大的数
思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...
- 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 ...
随机推荐
- 第五章 Spring3.0 、Hibernate3.3与Struts2的整合
5.1整合Spring与Hibernate 5.1.1使用MyEclipse加入Spring与Hibernate功能 使用MyEclipse工具主要是为了让工程拥有把数据表生成实体类与映射的功能.然后 ...
- ulimit 说明
ulimit官方描述 Provides control over the resources available to the shell and to processes started by it ...
- Unix/Linux环境C编程入门教程(6) 安装Fedora C/C++开发环境
安装Fedora C/C++开发环境 1 Fedora 是一个开放的.创新的.前瞻性的操作系统和平台,基于 Linux. 2.选择自定义配置 3.设置版本为10.0 4.选择稍后安装 5.选择64位 ...
- Android软件版本更新
转的:适合新手学习,但在实际项目中不可这么做. 以下是我转的内容: ================================================================= ...
- NOI2014 Day2
NOI2014 Day2 动物园 题目描述:给出一个字符串(长度为\(Len\)),设\(num[i]\)为字符串的前\(i\)个字符构成的子串(\(A\))中,满足\(A\)的前\(L\)个字符既是 ...
- python之lambda表达式
lambda函数小结 1.lambda表达式: 以前看人家写一个长式子就能干一件我写一个函数干的事情觉得好帅,现在通过学习知道了lambda表达式其原理就是一个函数,而且是一个只能处理简单功能的函数. ...
- Spring构造器注入、set注入和注解注入
记得刚开始学spring的时候,老师就反复的提到依赖注入和切面,平常的java开发中,在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种方法耦合度太高并且不容易测试,sp ...
- SQL学习之Insert的特殊用法(插入检索出的数据,表之间的数据复制)
1.插入检索出的数据 select * from dbo.Customers_1
- SQL学习之使用常用函数处理数据
一.在介绍使用函数处理数据前,先说下使用DBMS(数据库管理系统)处理数据所带来的问题! 1.与几乎所有的DBMS都同等的支持SQL语句(如SELECT)不同,每一个DBMS都有特定的函数,事实上,只 ...
- access 语句错误
一直说是语句错误,一直没有找出来是什么错误,原来access的语句需要在字段上套一个[],这是最正确的写法,关键是动软生成的是我们一贯用的,和标准还是有些差别的,害了我好久都不知道是哪里的问题