编程之美 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;
    }
}

 

posted @ 2018-04-13 13:46  xinyilovestudy  阅读(171)  评论(0编辑  收藏  举报