编写程序,对任意输入的若干个不相同的整数,输出其第k大的数html
咱们采用分治法解决这道题。 把这些数放在一个数组中,用分治法的话,咱们能够想到,怎样分治? 把一个数组分红若干个大小相等的子数组,而后在这些子数组中取中位数,再取这些中位数的中位数,用这个数就能够把数组划分为一个比它大的和比它小的数组。经过用这个数和咱们要求的数进行比较,若等于它,则直接返回这个数,若小于,则递归的对这个数前面的数组的这些数进行分治策略,若大于,则递归的对这个数后面的数组的这些数进行分治策略。java
$main()$里只有一个$SelectK()$方法,中包含有两个主要的方法,分别为取中位数$Median()$和划分$Divide()$方法。 \(Median()\): 首先,咱们把数组分为5个一组(据说通过证实,5个一组划分最科学),而后取每组的中位数,这时用的是$Median()$方法。具体的对每5个连续的数进行排序,而后把每组中的中位数即第3个数交换到数组的最左边,若是这些转移的数的个数多于5个,就再次调用$Median()$方法,直到最左边的数是这个数组的中位数的中位数。 \(Divide()\): 介绍划分方法,当求得中位数的中位数后,咱们就以这个数为基准,把当前进行排序的数组的段落进行划分,小于基准数的交换到基准数的左边,大于的交换至右边,而后比较要求的那个数和基准数是否相等,若是相等,则返回;若小于基准数,则递归左边的子数组;若大于基准数,则递归右边的子数组。算法
到这里,就是简单介绍一下这道题,这道题的主要算法在网上叫BFPRT算法,有兴趣的同窗能够去搜一下,若是不想搜的话,能够直接看我以前写的具体讲这道题分治算法背后的算法思想的文章分治策略-选择问题。数组
static void swap(int[]arr,int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } static void sortArr(int[] arr,int a,int b){ for(int i=a;i<b;i++){ for(int j=i+1;j<=b;j++){ if(arr[i]<arr[j]) swap(arr,i,j); } } } //找中位数的中位数 static int Median(int[] arr,int a,int b){ if(a==b) return a; int i=0; int n=0; for(i=a;i<b-5;i+=5){ sortArr(arr,i,i+4); n = i - a; swap(arr,a+n/5,i+2); } //下面是剩余的数 int last = b-i+1; if(last>0){ sortArr(arr,i,i+last-1); n = i - a; swap(arr,a+n/5,i+last/2); } n/=5; if(n==a) return a; return Median(arr,a,a+n); } //划分 static int Divide(int[]arr,int a,int b,int m){ swap(arr,m,a); int i = a; int j = b; int flag = arr[a]; while (i<j){ while (arr[j]<=flag && i<j) j--; arr[i] = arr[j]; while (arr[i]>=flag && i<j) i++; arr[j] = arr[i]; } arr[i] = flag; return i; } static int SelectK(int[] arr,int a,int b,int k){ int m = Median(arr,a,b); int i = Divide(arr,a,b,m); int x = i-a+1; if(x==k) return arr[i]; if(x>k) return SelectK(arr,a,i-1,k); return SelectK(arr,i+1,b,k-x); } public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("请输入要求的第k大的k:"); int k = in.nextInt(); int[] arr = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,100,99,98,97,96,95,94,93,92,91, 90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54, 53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26}; // System.out.println(arr.length); System.out.println("第"+k+"大为:"+SelectK(arr,0,arr.length-1,k)); }