题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
分析:
法1:如果允许修改输入的数组,可以基于快排的思想,使得比第k个数字小的所有数字都位于数组左边,比第k个数字大的数字都位于数组右边。这样调整以后位于数组中左边的k个数字就是最小的k个数字(但这k个数字不一定是排好序的)。
public List<Integer> getLeastNumbers_Solution(int [] input, int k) {
List<Integer> list=new ArrayList<>();
if(input==null||input.length==0||k<=0||k>input.length)
return list;
int left=0,right=input.length-1;
int index=parti(input,left,right);
while(index!=k-1) {
if(index<k-1) {
left=index+1;
}else {
right=index-1;
}
index=parti(input,left,right);
}
Arrays.sort(input, 0, k);
for(int i=0;i<k;i++)
list.add(input[i]);
return list;
}
public int parti(int []input,int left,int right) {
if(left>right)
return -1;
int i=left,j=right;
int temp=input[left];
while(i!=j) {
while(input[j]>=input[left]&&j>i)
j--;
while(input[i]<=input[left]&&i<j)
i++;
if(i<j) {
int tmp=input[i];
input[i]=input[j];
input[j]=tmp;
}
}
input[left]=input[i];
input[i]=temp;
return i;
}
法2:维护一个最大堆,当堆内数字小于k时,不断向堆内添加数字,直到堆内元素个数达到k。当堆内的数字等于k时,每次向堆内添加数字首先与堆顶元素比较,如果小于堆顶元素,则将堆顶元素移除,加入该元素;否则不做任何修改,继续遍历。
public List<Integer> getLeastNumbers_Solution1(int [] input, int k) {
List<Integer> list=new ArrayList<>();
int []a=new int[k];
if(input==null||input.length==0||k>input.length)
return list;
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2.compareTo(o1);
}
});
for(int i=0;i<input.length;i++) {
if(maxHeap.size()!=k) {
maxHeap.offer(input[i]);
}else if(maxHeap.peek()>input[i]) {
maxHeap.poll();
maxHeap.offer(input[i]);
}
}
int k1=0;
for(Integer i:maxHeap) {
a[k1]=i;
k1++;
}
Arrays.sort(a);
for(int i=0;i<k;i++)
list.add(a[i]);
return list;
}
博客给出输入n个整数找出最小K个数的问题,如输入4,5,1等8个数字,找出最小4个数字。并提供两种解决方法,一是基于快排思想调整数组,二是维护一个最大堆,根据堆内元素情况添加或替换元素。
4301

被折叠的 条评论
为什么被折叠?



