一、题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
二、思路分析及代码实现
方法一:先排序后取值
直接调用Arrays的排序算法sort,默认升序,然后选择前k个放入list中即可
时间:16ms
内存:9508k
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list=new ArrayList<>();
int len=input.length;
if(len<k)
return list;
Arrays.sort(input);
for(int i=0;i<k;i++){
list.add(input[i]);
}
return list;
}
}
方法二:使用冒泡排序挑选出小的K个数
因为冒泡排序每次都是挑选出数组中最大或最小的数,因此我们借助这个思想不将所有数组进行排序
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list=new ArrayList<>();
int len=input.length;
if(len<k)
return list;
for(int i=0;i<k;i++){
for(int j=0;j<len-i-1;j++){
if(input[j+1]>input[j]){
int temp=input[j];
input[j]=input[j+1];
input[j+1]=temp;
}
}
list.add(input[len-1-i]);
}
return list;
}
方法三:基于快速排序的partition函数
我们基于快速排序的partition函数,可以返回一个index值,这个K的左侧均小于它,右侧均大于它。
然后调用partition函数,判断返回的index和K值得大小判断我们所求得值在左侧还是右侧还是已经找到了
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
int len=input.length;
ArrayList<Integer> list=new ArrayList<>();
if(len<k)
return list;
int low=0, high=len-1;
while(low<=high){
int index=partition(input,low,high);
if(index==k-1){
//我们找到的左侧为所需要的数
break;
}else if(index<k-1){
//说明要找的在右侧部分
low=index+1;
}else{
high=index-1;
}
}
for(int i=0;i<k;i++){
list.add(input[i]);
}
return list;
}
private int partition(int[] arr, int start, int end){
int pivot=arr[end];
int smaller=start-1;
while(start<end){
if(arr[start]<pivot){
swap(arr,start++,++smaller);
}else{
start++;
}
}
swap(arr,end,++smaller);
return smaller;
}
private void swap(int[] arr, int a, int b){
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
}
存在的问题,会修改数组中的数据。
方法四:基于大顶堆
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<Integer>();
while(input == null || k <= 0 || k > input.length)
return list ;
int[] arr = new int[k]; //用于放最小的k个数
for(int i=0;i<k;i++)
arr[i] = input[i];//先放入前k个数
for(int i = k/2-1; i >= 0; i--){
adjustHeap(arr,i,k-1);//将数组调整成最大堆形式
}
for(int i = k;i < input.length; i++){
if(input[i]<arr[0]){ //存在更小的数字时
arr[0]=input[i];
adjustHeap(arr,0,k-1);//重新调整最大堆
}
}
for (int i = 0; i < arr.length; i++) {
list.add(arr[i]);
}
return list ;
}
//给一个数组,以及该数组的某个范围,将该范围构造成堆,start为最小值
private void adjustHeap(int[] arr,int start,int end){
int temp = arr[start];
int child = start*2+1;
while(child <= end){
if(child + 1 <= end && arr[child+1] > arr[child])
child++;
if(arr[child] < temp)
break;
arr[start] = arr[child];
start = child;
child = child*2+1;
}
arr[start] = temp;
}
}