题目:
输入整数数组 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
解法1:排序
/**
* 思路:
* 排序数组,获取k个值
*/
public int[] getLeastNumbers(int[] arr, int k) {
int[] result=new int[k];
//nlogn
Arrays.sort(arr);
for (int i=0;i<k;i++){
result[i]=arr[i];
}
return result;
}
时间复杂度:Onlogn
空间复杂度:On
解法2:新建数组
/**
* 思路:
* 在有限数据的情况下
* 创建一个大的数组,存放arr数组中的所有数据,把这些数据的值作为索引,出现的次数作为值
*/
public int[] getLeastNumbers(int[] arr, int k) {
int[] result=new int[k];
int index=0;
int[] count = new int[10000];
for (int i:arr){
count[i]++;
}
for (int i=0;i<count.length;i++){
while (count[i]>0){
if (index==k)return result;
result[index++]=i;
count[i]--;
}
}
return result;
}
时间复杂度:On^2
空间复杂度:On
解法3:heap(小顶堆)
/**
* 思路:
* 小顶堆实现
* heap,把数组元素放入堆,获取堆顶元素k次
*/
public int[] getLeastNumbers(int[] arr, int k) {
int[] result=new int[k];
PriorityQueue<Integer> heap = new PriorityQueue<>();
//插入操作logn,整体nlogn
for (int i:arr)heap.add(i);
for (int i=0;i<k;i++)result[i]=heap.remove();
return result;
}
时间复杂度:Onlogn
空间复杂度:On
解法4:大顶堆
/**
* 思路:
* 大顶堆实现
* 把前k个元素放入堆,后续的元素如果比堆顶元素小,移除堆顶元素,加入新元素
*/
public int[] getLeastNumbers(int[] arr, int k) {
int[] result=new int[k];
if (k==0)return result;
PriorityQueue<Integer> heap = new PriorityQueue<>((v1,v2)->v2-v1);
for (int i=0;i<arr.length;i++){
if (i<k)heap.add(arr[i]);
else {
if (heap.peek()>arr[i]){
heap.remove();
heap.add(arr[i]);
}
}
}
int i=0;
for (int num : heap)result[i++]=num;
// for (int i=0;i<k;i++)result[i]=heap.remove();
return result;
}
时间复杂度:Onlogn
空间复杂度:On