劍指offer 最小的k個數

題目描述

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

 

解法一:根據快速排序,基於數組的第k個數字來調整,使得k左邊的數字都小於k,k右邊的數字都大於k。

調整後,左邊的k個數字就是最小的k個數字,時間複雜度O(n)。

/**
 * @author yuan
 * @date 2019/2/19
 * @description 基於partition,時間複雜度O(n)
 */
public class 最小的K個數 {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<>(input.length);
        if (k < 1 || k > input.length) {
            return result;
        }
        int l = 0, r = input.length - 1;
        int index = partition(input, l, r);
        while (index != k - 1) {
            if (index > k - 1) {
                r = index - 1;
                index = partition(input, l, r);
            } else {
                l = index + 1;
                index = partition(input, l, r);
            }
        }
        for (int i = 0; i < k; i++) {
            result.add(input[i]);
        }
        return result;
    }

    /**
     * 切片
     * @param a
     * @param left
     * @param right
     * @return
     */
    private int partition(int[] a, int left, int right) {
        int i = left, j = right;
        int base = a[left];
        while (i < j) {
            while (i < j && a[j] >= base) {
                --j;
            }
            while (i < j && a[i] <= base) {
                ++i;
            }
            swap(a, i, j);
        }
        swap(a, left, i);
        return i;
    }

    private void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

 

解法二:用最大堆,時間複雜度O(nlgk)

先創建一個大小爲k的堆,接下來每次讀取一個整數,當堆的數字小於k,直接放入堆中。

若堆已經有k個數字,將堆中最大的值和當前整數比較,如果當前整數小於堆的最大值,則將堆中的最大值替換爲當前整數。

如果當前整數比堆的最大值大,則不可能是最小的k個整數之一,直接拋棄。


/**
 * @author yuan
 * @date 2019/2/19
 * @description 最大堆,時間複雜度O(nlgk)
 * 用最大堆保存這k個數,每次只和堆頂比,如果比堆頂(堆中最大的元素)小,刪除堆頂,新數入堆。
 * 否則拋棄
 */
public class 最小的K個數 {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<>(input.length);
        int len = input.length;
        if (k > len || k < 1) {
            return result;
        }
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, Comparator.reverseOrder());
        for (int i = 0; i < len; i++) {
            if (maxHeap.size() < k) {
                maxHeap.offer(input[i]);
            } else if (input[i] < maxHeap.peek()) {
                // 如果當前整數比堆中最大的元素還小,用這個整數替換已有的最大值
                maxHeap.poll();
                maxHeap.offer(input[i]);
            }
        }
        result.addAll(maxHeap);
        return result;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章