java求最小的k个数

题目描述: 输入N个数,找出其中最小的K个数。例如,输入1,2,3,4,5,6,7,8,求最小的4个数,既输出1,2,3,4。

比较容易想到的的解法:对N个数进行排序,排序之后位于最前面的k个数就是最小的k个数字。
时间复杂度为O(n)的解法:仅适用于我们可以修改输入数组时

  • 使用Partition函数(O(n))进行划分,寻找数组中的第k个数字, 这样位于第k个数字左边的数字都比第k个数字小,位于第k个数字右边的数字都比第k个数字大。
    代码:

public class 最小的k个数 {
    
    
    // 使用partition进行求解,这样的话,比第k小的数字小的都位于数组的左边,比第k个数字大的都位于数组的右边
    private static void getMinKNumbers(int[] input, int k) throws Exception {
    
    
        if (input == null || input.length == 0 || k <= 0) {
    
    
            return;
        }
        int start = 0;
        int end = input.length - 1;
        int index = Partition(input, start, end);
        while (index != (k - 1)) {
    
    
            if (index > k - 1) {
    
    
                end = index - 1;
                index = Partition(input, start, end);
            } else {
    
    
                start = index + 1;
                index = Partition(input, start, end);// 时间复杂度为O(n)
            }
        }
        for (int i = 0; i < k; i++) {
    
    
            System.out.println(input[i]);
        }

    }

    private static int Partition(int[] input, int start, int end) throws Exception {
    
    
        if (input == null || start < 0 || end > input.length) {
    
    
            throw new Exception("in partition function, input param error.");
        }
        int partitionIndex = RandomInRange(start, end); // 随机生成partition的 index 
        int pivort = input[partitionIndex];
        swap(input, partitionIndex, end);
        int small = start - 1;
        for (int i = start; i < end; i++) {
    
    
            if (input[i] < pivort) {
    
    
                small++;
                if (small != i) {
    
    
                    // 如果两个下标相等的话,就不进行交换
                    swap(input, small, i);
                }
            }
        }
        small++;
        swap(input, small, end);
        return small;
    }

    private static void swap(int[] data, int index1, int index2) {
    
    
        int temp = data[index1];
        data[index1] = data[index2];
        data[index2] = temp;
    }


    /*随机生成划分的中心点*/
    private static int RandomInRange(int start, int end) {
    
    
        Random random = new Random();
        // nextInt(n)生成的随机数的范围不包括n,所以我们下面加1。
        return random.nextInt(end - start + 1) + start;
    }


    public static void main(String[] args) throws Exception {
    
    
        getMinKNumbers(new int[]{
    
    4, 5, 1, 6, 2, 7, 3, 8}, 4);
    }
}

猜你喜欢

转载自blog.csdn.net/liu_12345_liu/article/details/103652957
今日推荐