剑指offer—40.最小的K个数—分析及代码(Java)

2023-10-30

一、题目

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

二、分析及代码

1. 排序

(1)思路

最直观的方法:对数组进行排序,前 k 个数即为所求解。
这种方法简单直观,但时间复杂度较高,为 O(nlogn)。

(2)代码

import java.util.*;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> ans = new ArrayList<>();
        if (input == null || input.length < k)
            return ans;
        Arrays.sort(input);
        for (int i = 0; i < k; i++)
            ans.add(input[i]);
        return ans;
    }
}

(3)结果

运行时间:17 ms,占用内存:9480 K。

2. Partition

(1)思路

可结合快速排序中的 Partition 方法,通过迭代将最小的 K 个数全部交换到前 K 个位置。
这种方法时间复杂度为 O(n)。

(2)代码

import java.util.*;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> ans = new ArrayList<>();
         if (input == null || input.length == 0 || k <= 0 || k > input.length)
            return ans;
        int begin = 0, end = input.length - 1;
        int p = Partition(input, begin, end);
        while (p != k - 1) {
            if (p < k - 1)
                begin = p + 1;
            else
                end = p - 1;
            p = Partition(input, begin, end);
        }
        for (int i = 0; i < k; i++)
            ans.add(input[i]);
        return ans;
    }
     
    public int Partition(int[] input, int begin, int end) {
        int pivot = input[begin];
        int low = begin, high = end;
        while (low < high) {
            while (low != high && input[high] >= pivot)
                high--;
            swap(input, low, high);
            while (low != high && input[low] <= pivot)
                low++;
            swap(input, low, high);
        }
        return high;
    }
     
    public void swap(int[] input, int a, int b) {
        int temp = input[a];
        input[a] = input[b];
        input[b] = temp;
    }
}

(3)结果

运行时间:23ms,占用内存:9628。

3. 堆

(1)思路

可以建立一个容量为 k 的大顶堆,当堆中元素个数 < k 时,添加遍历到的元素;当堆中元素个数等于 k 时,若遍历到的元素小于堆顶,抛出堆顶元素并加入新元素,否则跳过遍历到的元素。
这种方法时间复杂度为 O(nlogk),特别适合处理数据流。

(2)代码

import java.util.*;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> ans = new ArrayList<>();
         if (input == null || input.length == 0 || k <= 0 || k > input.length)
            return ans;
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer> (k, new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return b.compareTo(a);
            }
        });
        
        for (int i = 0; i < input.length; i++) {
            if (maxHeap.size() < k)
                maxHeap.offer(input[i]);
            else if (input[i] < maxHeap.peek()) {
                maxHeap.poll();
                maxHeap.offer(input[i]);
            }
        }
        
        for (Integer i : maxHeap) {
            ans.add(i);
        }
        return ans;
    }
}

(3)结果

运行时间:23ms,占用内存:9536。

三、其他

暂无。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

剑指offer—40.最小的K个数—分析及代码(Java) 的相关文章

随机推荐