最小的K个数

题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

思路:堆排序中每趟可以输出最小元素,所以,借助堆排序可以得到最小的K个数。

步骤:

1 创建无元素的ArrayList对象。

2 如果数组为空或者k不是正整数,则返回指向ArrayList对象的引用。

3 获取数组容量。如果数组容量小于k,则返回指向ArrayList对象的引用;如果数组容量是1且k是1即结果只有1个元素,则把该元素添加到ArrayList对象中,返回指向ArrayList对象的引用。

4 构造初始小顶堆。

5 k趟获取当前最小元素,并把该元素添加到ArrayList对象中。

6 返回指向ArrayList对象的引用。

Java代码:

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int[] arr, int k) {
        // 创建ArrayList对象
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        // 如果数组为空或者k不是正整数
        if (arr == null || k <= 0) {
            return arrayList;
        }
        
        // 获取数组容量
        int len = arr.length;
        // 如果数组容量小于k
        // 如果数组容量是1且k是1即结果只有1个元素
        if (len < k) {
            return arrayList;
        }
        else if (len == 1 && k == 1) {
            arrayList.add(arr[0]);
            return arrayList;
        }
        
        // 设定可访问的最大下标
        len--;
        
        // 构造初始小顶堆
        buildMinHeap(arr, len);
        // k趟获取当前最小元素 数组下标从0开始
        for (int i = len, low = len - k + 1; i >= low; i--) {
            arrayList.add(arr[0]);
            
            // 交换堆顶元素和堆底元素
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            
            // 把剩余的i-1个元素建成堆
            adjustDown(arr, 0, i - 1);
        }
        
        return arrayList;
    }
    
    // 构造初始小顶堆
    private void buildMinHeap(int[] arr, int len) {
        // 反复调整堆
        for (int i = len / 2 - 1; i >= 0; i--) {
            adjustDown(arr, i, len);
        }
    }
    
    // 把当前结点所在的子树建成小顶堆
    private void adjustDown(int[] arr, int parent, int len) {
        // 暂存双亲结点值
        int temp = arr[parent];
        // 沿着较小的孩子结点向下筛选
        for (int child = 2 * parent + 1; child <= len; child = 2 * child + 1) {
            // 获取较小孩子结点的下标
            if (child + 1 <= len && arr[child + 1] < arr[child]) {
                child++;
            }
            
            // 筛选结束
            if (temp <= arr[child]) {
                break;
            }
            
            // 把孩子结点值赋到双亲结点上
            arr[parent] = arr[child];
            // 把孩子结点的下标赋给双亲结点
            parent = child;
        }
        
        // 把双亲结点值放在最终位置上
        arr[parent] = temp;
    }
}

 

posted on 2025-11-29 15:12  王景迁  阅读(0)  评论(0)    收藏  举报

导航