【题目描述】输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
【解题思路1】
//1.对数组按照从小到大的顺序,进行全排序。
//2.取数组的前k个节点
//3.注意输入的k的边界情况
【源码1】
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
if(input == null){
return null;
}
int len=input.length;
ArrayList arr = new ArrayList();
if(len == 0 || k==0 || k>len){
return arr;
}
Arrays.sort(input);
for(int i=0; ireturn arr;
}
}
a. 注意测试用例的边界情况。输入的数组可能为null,也可能为空数组,即长度为零。
b. k>input.length 的情况可能存在,或者k=0。
【解题思路2】在“思路1”的基础上改进一下
//1. 采用冒泡排序的思想,只冒泡k次。
//2. 冒泡出来的k个最小值,即符合要求
【源码2】
import java.util.ArrayList;
public class Solution {
public static ArrayList GetLeastNumbers_Solution(int [] input, int k) {
if(input == null){
return null;
}
int len = input.length;
ArrayList al = new ArrayList();
if (k > len) {
return al;
}
for (int i = 0; i < k; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (input[j] < input[j + 1]) {
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
}
}
al.add(input[len - i - 1]);
}
return al;
}
}
【解题思路3】
//1. 利用简单选择排序,每次挑选当前无序区里最小的值出来。
//2. 进行k次简单选择排序,得到要求的值。
【源码3】
import java.util.ArrayList;
public class Solution{
public static ArrayList GetLeastNumbers_Solution(int [] input, int k) {
if(input == null){
return null;
}
int len = input.length;
ArrayList arr = new ArrayList();
if (k > len || k==0 || len==0) {
return arr;
}
int min = 0; //标记最小元素的下标
for (int i = 0; i < k; i++) {
min = i;
for (int j = i+1; j < len; j++) {
if (input[j] < input[min]) {
min = j;
}
}
int temp = input[i];
input[i] = input[min];
input[min] = temp;
arr.add(input[i]);
}
return arr;
}
}
【解题思路4】
//1. 利用堆排序,O(N logK),适合处理海量数据。遍历输入数组,将前k个数插入到推中。
//2. 继续从输入数组中读入元素做为待插入整数,并将它与堆中最大值比较:如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,则抛弃这个数,继续读下一个数。
//3. 这样动态维护堆中这k个数,以保证它只储存输入数组中的前k个最小的数,最后输出堆即可。
【源码4】
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
ArrayList result = new ArrayList();
int length = input.length;
if(k > length || k == 0){
return result;
}
PriorityQueue maxHeap = new PriorityQueue(k, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
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;
}
}
【解题思路5】
//1. 利用快速排序中的获取分割(中轴)点位置函数getPartitiion。
//2. 基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。
//3. 调整之后,位于数组左边的k个数字就是最小的k个数字(这k个数字不一定是排序的)。复杂度为O(N)。
【源码5】
链接:https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf
来源:牛客网
import java.util.ArrayList;
public class Solution {
public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
ArrayList aList = new ArrayList();
if(input.length == 0 || k > input.length || k <= 0)
return aList;
int low = 0;
int high = input.length-1;
int index = Partition(input,k,low,high);
while(index != k-1){
if (index > k-1) {
high = index-1;
index = Partition(input,k,low,high);
}else{
low = index+1;
index = Partition(input,k,low,high);
}
}
for (int i = 0; i < k; i++)
aList.add(input[i]);
return aList;
}
int Partition(int[] input,int k,int low,int high){
int pivotkey = input[k-1];
swap(input,k-1,low);
while(low < high){
while(low < high && input[high] >= pivotkey)
high--;
swap(input,low,high);
while(low < high && input[low] <= pivotkey)
low++;
swap(input,low,high);
}
return low;
}
private void swap(int[] input, int low, int high) {
int temp = input[high];
input[high] = input[low];
input[low] = temp;
}
}
【解题思路6】
//利用红黑树,因为C++中有该数据结构的实现multiset,而java中并没有。所以在此不再赘述。
可参考C++的实现。
【源码6】
参考
https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf