输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4
思路1:快排,取最小四个
思路2:最大堆保存这k个数,每次只和堆顶比,如果比堆顶小,删除堆顶,新数入堆
快排都快忘了,-_-||,也算复习一下了
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
int len = input.length;
if( k > len || input == null){ //判断数组是否为空,以及k是否大于数组长度
return result;
}
quickSort(input,0,len-1);//快排开始
for(int i=0;i<k;i++){
result.add(input[i]);
}
return result;
}
public static void quickSort(int[] arr,int l,int r){
if(l < r){
swap(arr,l +(int) (Math.random() * (r - l + 1)),r);
int[] p = partition(arr,l,r);
quickSort(arr,l,p[0]-1);
quickSort(arr,p[1]+1,r);
}
}
public static int[] partition(int[] arr, int l, int r) {//小于的在左边,等于的在中间,大于的在右边
int less = l - 1;//小域指针
int more = r;//大域指针
while(l < more){
if(arr[l] < arr[r]){
swap(arr,++less,l++);//当前值小于最右侧值时,小域扩大1,l继续往右走
}else if(arr[l] > arr[r]){
swap(arr,--more,l);//当前值大于最右侧值时,大域扩大1,交换最右侧值与当前值,l不动,以便下次判断
}else {
l++;//当前值等于最右侧值,l往右走,两个域不变
}
}
swap(arr,more,r);
return new int[] {less+1,more};
}
public static void swap(int[] arr, int l,int r) {
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
@Test
public void fun1(){
int array[] = {4,5,1,6,2,7,3,8};
int n = 4;
ArrayList<Integer> a = GetLeastNumbers_Solution(array,n);
System.out.println(a);
}
最大堆思想:
ArrayList<Integer> result = new ArrayList<Integer>();
int length = input.length;
if(k > length || k == 0){
return result;
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
//PriorityQueue保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的大小进行重新排序。
// 因此当调用peek方法活着pull方法来取出队列中的元素时,并不是取出最先进入队列的元素,而是取出队列中最小的元素
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);//poll方法改为取最大
}
});
for (int i = 0; i < length; i++) {
if (maxHeap.size() != k) {
maxHeap.offer(input[i]);
} else if (maxHeap.peek() > input[i]) {//当堆顶元素大于当前值时,弹出堆顶,当前值入堆进行调整
Integer temp = maxHeap.poll();
temp = null;
maxHeap.offer(input[i]);
}
}
for (Integer integer : maxHeap) {
result.add(integer);
}
return result;