问题
面试题40. 最小的k个数
难度简单92收藏分享切换为英文关注反馈
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入: arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 100000 <= arr[i] <= 10000
解答一
利用最小堆,使用 Java 的 util 包中的 priorityQueue ,将数组全部元素添加到 priorityQueue 中,然后依次取出 k 个元素,这些元素就是前 k 个 最小的元素
示例代码:
class Solution {public int[] getLeastNumbers(int[] arr, int k) {PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(arr.length);int[] smallest = new int[k];for(int i = 0; i < arr.length; i ++)priorityQueue.add(arr[i]);for(int i = 0; i < k; i ++)smallest[i] = priorityQueue.poll();return smallest;}}
执行结果:
执行用时 :28 ms, 在所有 Java 提交中击败了20.59 的用户。
内存消耗 :41.3 MB, 在所有 Java 提交中击败了100.00%的用户。
解答二
利用快速排序的思想,切分数组,依次比较切割点是否等于 k, 如果等于 k,那么左区间就是前 k 个元素。如果不等于,那么就继续进行切割
class Solution {public int[] getLeastNumbers(int[] arr, int k){if(arr.length == 0 || k == 0) return new int[0];int v = 0;int lo = 0, hi = arr.length -1;while(true){v = partition(arr, lo, hi);if(v+1 < k)lo = v + 1;else if(v+1 > k)hi = v - 1;elsebreak;}int[]res = new int[k];for(int i = 0; i < k; i ++)res[i] = arr[i];return res;}private int partition(int[] arr, int lo, int hi){int v = arr[lo];int i = lo+1, j = hi;while(i <= j){if(arr[i] > v)swap(arr, i, j--);elsei ++;}swap(arr, j, lo);return j;}private void swap(int[] arr, int i , int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}
执行结果:
执行用时 :3 ms, 在所有 Java 提交中击败了84.05% 的用户
内存消耗 :41 MB, 在所有 Java 提交中击败了100.00% 的用户
