寻找最大的k个数
来源:互联网 发布:ae软件下载官方中文版 编辑:程序博客网 时间:2024/06/05 14:12
题目描述:输入n个整数,输出其中最大的k个。
举例:输入序列1、2、3、4、5、6、7、8,输出最大的4个数字为5、6、7、8。
可能存在的条件限制:
要求 时间 和 空间消耗最小、海量数据、待排序的数据可能是浮点数等
方法一:对所有元素进行排序,之后取出前K个元素,不提倡使用
思路:使用最快排序算法,选择快排 或 堆排
时间复杂度:O(n*logn) + O(K) = O(n*logn)
特点:需要对全部元素进行排序,K = 1 时,时间复杂度也为O(n*logn)
注意:题中只需得到最大的K个数,而不需要对后面N-K个数排序
方法二:只需要对前K个元素排序,不需要对N-K个元素进行排序,不提倡使用
思路:使用 选择排序 或 起泡排序,进行K次选择,可得到第k大的数
时间复杂度:O(n*k)
思路:寻找第K个大元素。
具体方法:使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求。
在数组S中找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。
这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
时间复杂度:因为每次只选择一部分递归,所以时间复杂度为N(1+1/2+1/4+....+1/x)<2N,所以复杂度为O(N).
若随机选取枢纽,线性期望时间O(N)。
若选取数组的“中位数的中位数”作为枢纽,最坏情况下的时间复杂度O(N)
以下代码用的是中位数法,得到最大的K个数。
下面的方法是找到第K个最大元素,后K个数即为前K个最大的数。
public static void main(String[] args) { searchKMax s = new searchKMax(); int a[]={20,100,4,2,87,8,9,5,46,260}; int Len=a.length; int K=5; s.FindKMax(a , 0 , Len- 1 , K); for(int i = Len-K ; i < Len; i++){ System.out.print(a[i]+" "); }}/*查找数组第K个最大的元素,index:返回数组中最大元素中第K个元素的下标(从0开始编号),high为数组最大下标*/int FindKMax(int a[],int low,int high,int k){ int mid; int index=-1; if(low < high){ mid = partition(a , low , high); int rightlen = high - mid + 1; //右半边的长度 if(rightlen == k){ index=mid; //返回第k个位置 }else if(rightlen < k){ index=FindKMax(a , low , mid-1, k-rightlen); }else{ index=FindKMax(a , mid + 1 , high , k); } } return index;}/* * 将其他数与枢纽元比较,比枢纽元小的放在枢纽元左边,比它大的放在右边,划分为两个部分 */public int partition(int[] array,int left,int right){//选取枢纽元,不要选择第一个元素,一般用三数中值法求枢纽元,把枢纽元放到最左边int pivot = median3(array,left,right);int low = left+1;//从第二个数开始找int high = right;//找到第一个比枢纽元小的数,两者交换while(true){//找到第一个比枢纽元大的数while(array[low] <= pivot && low < high)low++;//找到第一个第枢纽元小的数while(array[high] > pivot)high--;//如果左指针<右指针,则将两者交换if(low < high){swap(array,low,high);}else{break;}}/* * 将放在最左边的枢纽元与high指针上的数交换, * 至此枢纽元左边的数都是小于它的数,右边的数都是大于它的数 */swap(array,left,high);return high;}/* * 三数中值分割法确定枢纽元,取left,right,center三个数的中值 */public int median3(int[] array ,int left,int right){int center = (left+right)/2;if(array[left] > array[center]){swap(array,left,center);}if(array[left] > array[right]){swap(array,left,right);}if(array[right] < array[center]){swap(array,right,center);}//经过以上三个判断,中值在center位上swap(array,center,left);//把枢纽元放在最左边return array[left];//枢纽元的值}/* * 将i和j上的数字交换 */public void swap(int[] array,int i,int j){int temp = array[i];array[i] = array[j];array[j] = temp;}
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的k个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的k个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的K个数
- 寻找最大的k个数
- ios-实现本地通知(UILocalNotification)
- favicon add in wordpress
- js暂停(休眠)代码一段时间后继续执行代码
- 测试用例设计白皮书--错误推测方法
- 分享一个链接
- 寻找最大的k个数
- Golang_tag
- 测试用例设计白皮书--因果图方法
- HDU 4979: 更好的DLX模板 + 打表
- 二维数组的行地址与列地址应用举例
- Linux 开发板网络设置
- OK6410(s3c6410)时钟系统
- Android SQLite数据库使用 学习与代码实践
- 测试用例设计白皮书--判定表驱动分析方法