找到第k个最大的数

15 篇文章 0 订阅
8 篇文章 0 订阅

一、问题描述

给定一个数组,数组中的数据无序,在一个数组中找出其第k个最小的数,例如对于数组x,x = {3,2,1,4,5,6},则其第2个最小的数为2。


二、解题思路

算法跟快排的思想相似,首先在数组中选取一个数centre作为枢纽,将比centre小的数,放到centre的前面将比centre大的数,放到centre的后面。如果此时centre的位置刚好为k,则centre为第k个最小的数;如果此时centre的位置比k前,则第k个最小数一定在centre后面,递归地在其右边寻找;如果此时centre的位置比k后,则第k个最小数一定在centre后面,递归地在其左边寻找。


注意:centre的位置=其下标值+1,因为数组中的第一个元素的下标为0。


从上面的描述中,我们可以看到这个算法运用了减治的方法求解。减治的思想与分治非常相似,同样是在一次操作中,削减问题的规模,只是分治把每个子问题求解后,要合并每个子问题的解才能得到问题,而减治的方法,却不用合并子问题的解,子问题的解,直接就是原问题的解。举个例子来说,就像快排和二分查找算法,前者是分治,后者是减治。因为快排要等到所有的子数组都排完序,原数组才有序,而二分查找却不用,它每执行一次查找,直接丢弃一半的数组,而不用合并子问题的解。不过也有不少书,把他们都归为分治法。

  1. /** 
  2.  * 输入n个整数,找出其中最小的k个整数,找出其中最小的k个数。 
  3.  * 例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字为1,2,3,4 
  4.  */  
  5.    
  6. public class E30KLeastNumbers {  
  7.     // 使用partition函数  
  8.     public int partition(int[] arr, int left, int right) {  
  9.         int result = arr[left];  
  10.         if (left > right)  
  11.             return -1;  
  12.   
  13.         while (left < right) {  
  14.             while (left < right && arr[right] >= result) {  
  15.                 right--;  
  16.             }  
  17.             arr[left] = arr[right];  
  18.             while (left < right && arr[left] < result) {  
  19.                 left++;  
  20.             }  
  21.             arr[right] = arr[left];  
  22.         }  
  23.         arr[left] = result;  
  24.         return left;  
  25.     }  
  26.     public int[] getLeastNumbers(int[] input,int k){  
  27.         if(input.length == 0 || k<= 0)  
  28.             return null;  
  29.         int[] output = new int[k];  
  30.         int start = 0;  
  31.         int end = input.length-1;  
  32.         int index = partition(input,start,end);  
  33.         while(index != k-1){  
  34.             if(index > k-1){  
  35.                 end = index -1;  
  36.                 index = partition(input,start ,end);  
  37.             }  
  38.             else{  
  39.                 start = index+1;  
  40.                 index = partition(input,start ,end);  
  41.             }  
  42.         }  
  43.         for(int i = 0;i<k;i++){  
  44.             output[i] = input[i];  
  45.         }  
  46.         return output;  
  47.     }  
  48.     public static void main(String[] args){  
  49.         int[] arr= {4,5,1,6,2,7,3,8};  
  50.         E30KLeastNumbers test = new E30KLeastNumbers();  
  51.         int[] output=test.getLeastNumbers(arr, 4);  
  52.         for(int i = 0;i<output.length ;i++){  
  53.             System.out.print(output[i]+",");  
  54.         }  
  55.     }  
  56. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值