面试题40. 最小的k个数

输入整数数组 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.快排变形:

class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0) {
return new int[0];
} else if (arr.length <= k) {
return arr;
}
int low = 0;
int high = arr.length-1;
int pos = partition(arr,low,high);
while(low<high&&pos!=k-1){
if(low<high&&pos>k-1){
high = pos-1;
}else{
low = pos+1;
}
pos = partition(arr,low,high);

}
int[] res = new int[k];
System.arraycopy(arr,0,res,0,k);
return res;


}
public int partition(int[] arr,int less,int more){

int base = arr[less];
while(less<more){
while(less<more&&arr[more]>=base){
more--;
}
arr[less] = arr[more];
while(less<more&&arr[less]<=base){
less++;
}
arr[more] = arr[less];
}
arr[less] = base;
return less;
}

}

2.构建小根堆

class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0) {
return new int[0];
} else if (arr.length <= k) {
return arr;
}
for(int i = arr.length/2-1;i>=0;i--){
adjusHeap(arr,i,arr.length);
}

for(int j = arr.length-1;j>=arr.length-k;j--){
swap(arr,0,j);
adjusHeap(arr,0,j);
}

int[] res = new int[k];
System.arraycopy(arr,arr.length-k,res,0,k);
return res;


}
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public void adjusHeap(int[] arr,int index,int heapSize){
int temp = arr[index];
for(int k = index*2+1;k<heapSize;k=k*2+1){
if(k+1<heapSize&&arr[k]>arr[k+1]){
k++;
}
if(arr[k]<temp){
arr[index] = arr[k];
index = k;
}else{
break;
}
}
arr[index] = temp;

}

}