输入整数数组 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]
限制:
来源:
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof
题解一:
排序:排序后返回数组的前 k 个数即可
时间复杂度和空间复杂度未定,取决于所使用的排序算法
/**
* 剑指 Offer 40. 最小的k个数
*/
public int[] getLeastNumbers(int[] arr, int k) {
Arrays.sort(arr);
return Arrays.copyOf(arr, k);
}
题解二:
快排:利用快速排序算法(升序)基准数左边的数均小于基准数的特点,对原数组进行快排,若在某一趟快排过程中基准数左边(含基准数)的元素个数等于 k 则直接返回子数组即可
时间复杂度 O(Nlog2N):快排平均时间复杂度为 NlogN
空间复杂度 O(N):快排递归深度平均为 O(log2N),最差为 O(N)
/**
* 剑指 Offer 40. 最小的k个数
*/
public int[] getLeastNumbers(int[] arr, int k) {
return k >= arr.length ? arr : quickSort(arr, 0, arr.length - 1, k);
}
public static int[] quickSort(int[] arr, int start, int end, int k) {
int i = start;
int j = end;
// 每轮快排选取最左边的元素作为基准数
int base = arr[start];
while (i < j) {
// 从右往左寻找不大于基准数的元素
while (j > i && arr[j] >= base) {
j--;
}
// 从左往右寻找不小于基准数的元素
while (i < j && arr[i] <= base) {
i++;
}
// 交换
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// 移动基准数
arr[start] = arr[i];
arr[i] = base;
// 左序列比基准数小的元素个数大于 k,左序列继续快排
if (i > k) {
return quickSort(arr, start, i - 1, k);
}
// 左序列比基准数小的元素个数小于 k,右序列快排
if (i < k) {
return quickSort(arr, i + 1, end, k);
}
return Arrays.copyOf(arr, k);
}