难度简单
输入整数数组 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 <= 10000
-
0 <= arr[i] <= 10000
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (arr.length == 0 || k == 0) {
return new int[0];
}
return helper(arr, 0, arr.length - 1, k - 1);
}
private int[] helper(int[] arr, int start, int end, int k) {
// 每快排切分1次,找到排序后下标为j的元素,如果j恰好等于k就返回j以及j左边所有的数;
int j = quickSearch(arr, start, end);
if (j == k) {
return Arrays.copyOf(arr, j + 1);
}
// 否则根据下标j与k的大小关系来决定继续切分左段还是右段。
return j > k? helper(arr, start, j - 1, k): helper(arr, j + 1, end, k);
}
private int quickSearch(int[] arr, int start, int end) {
int value = arr[start];
int left =start;
int right =end+1;
while (true){
while (++left<=end&&arr[left] < value);
while (--right<=end&&arr[right]> value);
if (left >= right) {
break;
}
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
arr[start] = arr[right];
arr[right] = value;
return right;
}
}
堆
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] vec = new int[k];
if (k == 0) { // 排除 0 的情况
return vec;
}
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer num1, Integer num2) {
return num2 - num1;
}
});
for (int i = 0; i < k; ++i) {
queue.offer(arr[i]);
}
for (int i = k; i < arr.length; ++i) {
if (queue.peek() > arr[i]) {
queue.poll();
queue.offer(arr[i]);
}
}
for (int i = 0; i < k; ++i) {
vec[i] = queue.poll();
}
return vec;
}
}