题目详情
题目链接
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
提示:
0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))
算法原理
我们可以用快速选择算法来解决:
- 随机选择一个基准元素key
- 递归地将数组分成三部分:<key区;=key区;>key区。
- 分类讨论
编写代码
class Solution {
public int[] smallestK(int[] nums, int k) {
qsort(nums, 0, nums.length - 1, k);
int[] ret = new int[k];
for (int i = 0; i < k; i++)
ret[i] = nums[i];
return ret;
}
public void qsort(int[] nums, int l, int r, int k) {
if (l >= r) return; // 递归出口
// 1. 随机选择一个基准元素key
int key = nums[new Random().nextInt(r - l + 1) + l];
int left = l - 1, right = r + 1, i = l;
//2. 将数组分成三块
while (i < right) {
if (nums[i] < key) swap(nums, ++left, i++);
else if (nums[i] == key) i++;
else swap(nums, --right, i);
}
// 3.分类讨论
int a = left - l + 1, b = right - left -1;
if (a > k) qsort(nums, l, left, k);
else if (a + b >= k) return;
else qsort(nums, right, r, k - a - b);
}
public void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}