剑指offer-最小的K个数
题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路:
- 思路一:使用快排的思想,选择一个基准数,做快排,当基准数的位置为k时,前k个就是我们要找的
- 思路二:维护一个大小为k的最大堆,当有新数进来,若该数字大于堆顶,则直接跳过该数字,否则,将该数字与堆顶的数字交换,然后调整堆为最大堆,这样最后堆中的k个数就是最小的K个数字
- 最大的k个数同理,找最大维护最小堆即可
code
public void adjustMaxHeap(int[] arr,int i,int len) {
int tmp=arr[i];
for (int k=i*2+1;k<len;k=k*2+1) {
if(k+1<len && arr[k]<arr[k+1]) {
k++;
}
if(tmp<arr[k]) {
arr[i]=arr[k];
i=k;
} else {
break;
}
}
arr[i]=tmp;
}
public void buildMaxHeap(int[] arr) {
int len=arr.length;
for (int i = len/2-1; i>=0 ; --i) {
adjustMaxHeap(arr,i,len);
}
}
public void sortAscHeap(int[] arr) {
buildMaxHeap(arr);
int len=arr.length;
for (int i = len-1; i>0 ; --i) {
int tmp=arr[i];
arr[i]=arr[0];
arr[0]=tmp;
adjustMaxHeap(arr,0,i);
}
}
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list=new ArrayList<>();
if(k==0 || input==null || input.length==0 || input.length<k) {
return list;
}
int[] heap=Arrays.copyOfRange(input,0,k);
buildMaxHeap(heap);
int len=input.length;
for (int i = k; i < len; i++) {
if(input[i]>heap[0]) {
continue;
} else {
heap[0]=input[i];
adjustMaxHeap(heap,0,k);
}
}
sortAscHeap(heap);
System.out.println(Arrays.toString(heap));
for (int i = 0; i < k; i++) {
list.add(heap[i]);
}
return list;
}