剑指Offer_29_最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
解题思路
-
解法1
大顶堆,存放k个数字,遍历数组,当堆的数量小于k,则直接加入堆,否则与堆顶元素比较,如果比堆顶元素小,则将堆顶元素移除,并添加当前元素。 -
解法2
我们可以根据快速排序的思想,找到数组中第k个元素,排在其前面的都是比他小的。
实现
- 解法1
import java.util.ArrayList;
import java.util.TreeSet;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if (input == null || input.length < k || k <= 0) return list;
TreeSet<Integer> set = new TreeSet<>();
for (int i : input) {
if (set.size() < k) set.add(i);
else {
if (set.last() > i) {
set.pollLast();
set.add(i);
}
}
}
list.addAll(set);
return list;
}
}
- 解法2
import java.util.ArrayList;
import java.util.Random;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if (input == null || input.length < k || k <= 0) return list;
//TreeSet<Integer> set = new TreeSet<>();
int par = partion(input, 0, input.length-1);
int start = 0, end = input.length - 1;
while (par != k-1){
if (par < k - 1){
start = par + 1;
par = partion(input,par + 1, end);
}
else {
end = par - 1;
par = partion(input,start,end-1);
}
}
for (int i = 0; i < k; i++){
list.add(input[i]);
}
return list;
}
private int partion(int[] input, int start, int end) {
if (start > end) return 0;
Random r = new Random();
int rd = r.nextInt(end- start + 1) + start;
int tmp = input[rd];
input[rd] = input[end];
input[end] = tmp;
int index =start -1;
for (int i = start; i < end; i++){
if (input[i] <= input[end]){
index++;
if (index != i){
tmp = input[index];
input[index] = input[i];
input[i] = tmp;
}
}
}
tmp = input[++index];
input[index] = input[end];
input[end] = tmp;
return index;
}
}