劍指offer 最小的k個數

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

當數據量很大的時候爲了節省空間,那就要使用堆排序

這裏我自己實現了堆的調整過程

 public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> list = new ArrayList<>();
        //k小於input的長度
        if(k > input.length || k<=0) return list;
        if (k == input.length) {
            for (int i = 0; i < input.length; i++) {
                list.add(input[i]);
            }
            return list;
        }
        //初始化樹
        int[] tree = new int[k];
        for (int i = 0; i < k; i++) {
            tree[i] = input[i];
        }

        //創建大頂堆
        //先獲取第一個非葉子節點的位置
        int begin = k / 2 - 1;
        for (int i = begin; i >= 0  ; i--) {
            adjustBigHeap(tree, i, k);
        }
        //此時tree[0]一直是4個數中最大的數
        for (int i = k; i < input.length; i++) {
            if(input[i] < tree[0]){
                //發現當前值比樹中最大值小,替換樹中最大值,再進行堆排序
                tree[0] = input[i];
                adjustBigHeap(tree, 0, k);
            }
        }
        for (int i = 0; i < k; i++) {
            list.add(tree[i]);
        }
        return  list;

    }

    /***
     * 大頂堆調整函數
     * 使用該方法創建大頂堆如節點個數爲n,數組爲tree,則第一個非葉子節點的index = n / 2 - 1
     * 則如此調用for (int i = index; i >= 0  ; i--) adjustBigHeap(tree, i, k);
     * @param tree
     * @param index
     * @param length
     */

    public void adjustBigHeap(int[] tree, int index, int length) {
        int left = index * 2 +  1;
        int right = index * 2 + 1;
        if(left >= length) return;//該節點是葉子節點
        int maxIndex;//標記左右節點中最大的那個節點
        if(right < length) maxIndex = left;//不存在右節點,比較左右節點
        else{
            if(tree[left] < tree[right]) maxIndex = right;
            else maxIndex = left;
        }
        if(tree[index] < tree[maxIndex]) {
            swap(tree, index, maxIndex);
            adjustBigHeap(tree, maxIndex, length);
        }
    }


public void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

其實java提供了類似堆的數據結構 優先隊列 PriorityQueue,是這個東西

有一個問題,就是它默認是小頂堆排序的,所以創建這個隊列的時候要修改它的排序規則,上代碼,這比之前就那個自己實現就舒服太多了

public ArrayList<Integer> GetLeastNumbers_Solution2(int[] input, int k) {
        ArrayList<Integer> list = new ArrayList<>();
        if(k > input.length || k == 0) return list;

        PriorityQueue<Integer> queue  = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        for (int i = 0; i < k ; i++) {
            queue.add(input[i]);
        }

        for (int i = k; i < input.length; i++) {
            if(input[i] < queue.peek()) {
                queue.poll();
                queue.add(input[i]);
            }
        }
        for (int num : queue) {
            list.add(num);
        }
        return list;
    }
發佈了142 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章