查找第k大的数
来源:互联网 发布:淘宝男装外贸原单店铺 编辑:程序博客网 时间:2024/04/30 09:24
查找第K个大数存在着很多方法,有些类似于查找前K个大的数。下面给出一些代码实现,可以完成这个功能。
1. 排序后查找
/******************************************* 第一种方法当然是排序,对整个数组进行排序,需要O(nlgn)的时间复杂度,在定位到第K个元素复杂度为O(1),故整体复杂度为O(nlgn). 为简单起见,整个数组的元素无重复,且假定为整数。*******************************************/#ifndef Method1_H#define Method1_H#include <algorithm>int SearchKthNumber(int array[],int length,int K){if(length<K)return array[length-1];std::sort(array,array+length);//注意这里第K大的数是length-K,而不是K-1return array[length-K];}#endif
2. 利用堆的性质/******************************************* 方法1对所有的元素进行排序存在着较大的浪费,另一种方法是建立一个为K个元素的最小堆结构,然后依次遍历剩下的元素来替换堆顶元素,这样每次调整复杂度为O(lgK),总共需要调整n-K次,因此时间复杂度为O(nlgK).比较方法1,可以得到一定的性能提升。而且这种方法在数据量较大时仍然可用。*******************************************/#ifndef Method2_H#define Method2_H#include <iostream>//辅助函数,用于建堆和调整堆结构void AdjustHeap(int array[],int i,int length){int left=2*i+1;int right=left+1;while(right<length){if(array[left]<array[i]&&array[right]<array[i]){if(array[left]<array[right]){std::swap(array[left],array[i]);i=left;}else{std::swap(array[right],array[i]);i=right;}}else if(array[left]<array[i]&&array[right]>array[i]){std::swap(array[left],array[i]);i=left;}else{std::swap(array[right],array[i]);i=right;}left=2*i+1;right=left+1;}if(left<length){if(array[left]<array[i])std::swap(array[left],array[i]);}}int SearchKthNumber(int array[],int length,int K){//建堆for(int i=K/2-1;i>=0;--i)AdjustHeap(array,i,K);for(int i=K;i<length;++i){if(array[i]>array[0]){ std::swap(array[0],array[i]); AdjustHeap(array,0,K);}}return array[0];}#endif
3.类似快速排序方法/****************************************** 第三种可以采用跟踪的方式,因为我们知道第K大的元素(如果采用降序排列的话)必然位于数组中K-1的位置。采用类似快速排序的方法,每一次对包含这个位置的数组进行分类,这样可以递减需要进行分类的数组个数,直至分类到第K-1个位置,此时这个位置上的数即为我们想要的结果。时间复杂度为T(n)=T(n/2)+T(n/4)+...+1,结果近似为O(n)。*******************************************/#ifndef Method3_H#define Method3_H#include <iostream>int Partition(int array[],int begin,int end) { //键值确定 int key=array[begin]; while(begin<end) { while(array[begin]>key) ++begin; while(array[end]<key) --end; //交换过程 if(begin<end) std::swap(array[begin],array[end]); } //返回的是键值所在元素位置,以此元素位置将数组划分为两部分 return begin; } /****************************************************/ /****************************************************/ //定位部分 void Quick_Location(int array[],int begin,int end,int K) { if(begin<end) { int middle=Partition(array,begin,end); if(K-1<middle) Quick_Location(array,begin,middle-1,K); else if(K-1>middle) Quick_Location(array,middle+1,end,K); } } int SearchKthNumber(int array[],int length,int K){Quick_Location(array,0,length-1,K);return array[K-1];}/****************************************************/ #endif修改部分:上述代码写的略显潦草,下面给出递归方法,原理同上,但代码更为简洁。<pre name="code" class="cpp">//// KthNumber.h// The_Kth_Number//// Created by CHM on 14-6-25.// Copyright (c) 2014年 CHM. All rights reserved.// select the kth begger number#ifndef The_Kth_Number_KthNumber_h#define The_Kth_Number_KthNumber_h#include <iostream>using namespace std;template <typename Type>Type Random_Select(Type array[],int begin,int end,int k){ int size=end-begin+1; if(size<k) cerr<<"There will not be correct result!"<<endl; int i=begin; int j=end; //随机选择一个键值分割,避免输入数据顺序影响 int rand_number=rand()%size; Type key=array[begin+rand_number]; //等同于快速排序中等分割,这里采用双端法 while(i<j) { while(array[i]<key) ++i; while(array[j]>key) --j; if(i<j) swap(array[i],array[j]); } int pre_number=i-begin; //位置i前面刚好有k-1个元素,则位置i处的元素就是第i个元素 if(pre_number==k-1) return array[i]; //前面第元素个数大于或者等于k,第k个元素位于前半部分 else if(pre_number>k-1) return Random_Select(array,begin,i-1,k); //否则,第k个元素位于后半部分 else return Random_Select(array,i+1,end,k-(pre_number+1)); }#endif4. 测试用代码
#include <iostream>//#include "Method1.h"//#include "Method2.h"#include "Method3.h"using namespace std;int main(){int a[]={6,5,4,15,14,13,3,2,1,12,11,10,9,8,7};int result=SearchKthNumber(a,15,10);cout<<result<<endl;system("pause");return 0;}
当然还存在着许多其他种方法,这里只是给出一部分。
0 0
- 查找第k大的数
- 查找数组中第K大的数
- 查找N个数中第K大的数
- 查找给定区间内第K大/小的数
- 查找N个数中第K大的数
- O(n)查找第k小(大)的数
- 第K大的数
- 第k大的数
- 第k大的数
- 第K大的数
- 第k大的数
- 第K大的数
- 第K大的数
- 第K大的数
- 第K大的数
- 查找问题整理(2)查找第K大的数Kth Order Statitic
- 查找前k大的数
- 查找前K大的数
- Android 双卡双待识别
- Matlab函数linspace简介
- 简单的数据库分页技术
- 设计模式学习02—工厂模式
- 字符串处理函数
- 查找第k大的数
- 因为磁盘io瓶颈导致mysql当机的问题
- CCLabelTTF 换行操作
- System V共享内存
- jQuery整理笔记一----jQuery开始
- javadoc如何生成API文档
- 《老罗Android》学习之HTTP (二) POST和GET提交数据
- TOPCODER SRM 612 DIV2
- 三天学好CAD的学法