【劍指Offer】29、最小的K個數


  題目描述:

  輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。

  解題思路:

  本題最直觀的解法就是將輸入的n個整數排序,排序之后位於最前面的k個數就是最小的k個數,這取決於排序的時間復雜度,最快為O(nlogn)。

  當我們可以對輸入的數組進行修改時,可以得到一種更快的解法。類似於快速排序的思想,基於Partition函數來解決這個問題,如果我們選取數組的第n個數字(記為key)來進行數組重排,那么比key小的所有數字都位於數組的左邊,比key大的所有數字都位於key之后,也就是數組的右邊。

  因此,我們只需要判斷key的下標是否等於k-1,等於時返回其左邊的K個數便是最小的K個數。當key的下標小於k-1時,就在右邊繼續划分,反之左邊繼續划分。由此我們可以得到以下代碼實現,時間復雜度為O(n)。

  編程實現(Java):

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        //方法一:排序
        //方法二:partition分組
        ArrayList<Integer> res=new ArrayList<>();
        if(input==null || input.length<=0 || k>input.length)
            return res;
        int len=input.length;
        int low=0,high=len-1;
        int index=-1;
        while(low<high && index!=k){
            index=partition(input,low,high);
            if(index>k)
                high=index-1;
            else
                low=index+1;
        }

        for(int i=0;i<k;i++)
            res.add(input[i]);
        return res;
    }
    //划分算法,返回的i左邊都比他小,右邊都比他大
    public int partition(int[] array,int low,int high){
        int i=low,j=high;
        int temp=array[low];
        
        while(i<j){
            while(i<j && array[j]>=temp)
                j--;
            if(i<j){
                array[i]=array[j];
                i++;
            }
            while(i<j && array[i]<temp)
                i++;
            if(i<j){
                array[j]=array[i];
                j--;
            }
        }
        array[i]=temp;
        return i;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM