编程之美 2.5
解法1:利用分治法,先将某个数排在正确得位置,即比他大的数在左边,比他小的数在右边。然后比较他及他后面的数与k的大小。
import java.util.*; public class Main{ public static void main(String[] args) { int[] nums={10,3,2,9,8,5,7,6,20,1}; int k=5; int[] res=new int[k]; int len=nums.length; res=deepFun(nums,0,len-1,k); for(int i=0;i<5;i++){ System.out.println(res[i]); } } public static int[] deepFun(int[] nums,int start,int end,int k){ int temp=nums[start]; int left=start; int right=end; while(left<right){ while(left<right && nums[right]<=temp){ right--; } if(left<right){ nums[left]=nums[right]; nums[right]=temp; } while(left<right && nums[left]>=temp){ left++; } if(left<right){ nums[right]=nums[left]; nums[left]=temp; } } int[] res=new int[k]; if(left-start+1==k){ System.arraycopy(nums,start,res,0,k); }else if(left-start+1>k){ res=deepFun(nums,start,left,k); }else{ System.arraycopy(nums,start,res,0,left-start+1); int[] next=deepFun(nums,left+1,end,k-left+start-1); System.arraycopy(next,0,res,left-start+1,k-left+start-1); } return res; } }
解法2:使用堆维持K个元素,挨个遍历N个元素。
import java.util.*; public class Main{ public static void main(String[] args) { int[] nums={10,3,2,9,8,5,7,6,20,1}; int k=7; int[] res=new int[k]; System.arraycopy(nums,0,res,0,k); for(int i=k/2;i>=0;i--){ adjustHeap(res,i,k-1); } int len=nums.length; for(int i=k;i<len;i++){ if(nums[i]>res[0]){ res[0]=nums[i]; adjustHeap(res,0,k-1); } } for(int i=0;i<7;i++){ System.out.println(res[i]); } } public static void adjustHeap(int[] res,int parent,int len){ int temp=res[parent]; int child=2*parent+1; while(child<=len){ if(child+1<=len && res[child+1]<res[child]){ child++; } if(res[child]<temp){ res[parent]=res[child]; parent=child; child=child*2+1; }else{ break; } } res[parent]=temp; } }
3.使用间隔分治法,将第K大的数找出来,再一次记录比他大的数
import java.util.*; public class Main{ public static void main(String[] args) { int[] nums={1,1,1,1,1,1,1,1,1,1,1,20}; int k=7; int[] res=new int[k]; int len=nums.length; int max=-1; int min=-1; for(int i=0;i<len;i++){ if(nums[i]>max){ max=nums[i]; } if(nums[i]<min){ min=nums[i]; } } while(max-min>1){ int mid=min+(max-min)/2; if(index(nums,mid)>=k){ min=mid; }else{ max=mid; } } int count=0; for(int i=0;i<len;i++){ if(nums[i]>min){ res[count++]=nums[i]; } } for(int i=count;i<k;i++){ res[i]=min; } for(int i=0;i<7;i++){ System.out.println(res[i]); } } public static int index(int[] nums,int mid){ int count=0; for(int i=0;i<nums.length;i++){ if(nums[i]>=mid){ count++; } } return count; } }