输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4
/*
使用partition, 一次partition过后会有一个元素被放到正确的位置上,
比如说最终放到索引i处,那么[0,i]这i+1个元素就是前i+1小的元素
我之前的使用方式, 并不是分支思想, 因为处理边界中要么有0, 有么要么有n-1, 并没有像分支算法那样缩小了处理空间
*/
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
//input check
if(k==0){
return new int[]{};
}
//
partitionArr(arr, 0, arr.length-1, k);
int[] res = new int[k];
for(int i=0; i<k; i++){
res[i] = arr[i];
}
return res;
}
private void partitionArr(int[] arr, int left, int right, int k){
int index = partition(arr, left, right);
if(index+1 == k){
return;
}
else if(index+1 > k ){
partitionArr(arr, left, index-1, k);
}
else{
partitionArr(arr, index+1, right, k);
}
}
private int partition(int[] arr, int left, int right){
int small = left-1, big = right, pivot = arr[right], p = left;
while(p<big){
if(arr[p] <= pivot){
swap(arr, ++small, p++);
}else{
swap(arr, --big, p);
}
}
swap(arr, p, right);
return p;
}
private void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<>();
if(k==0)
return res;
if(input==null || input.length==0)
return res;
if(input.length < k)
return res;
//
int index = partition(input, 0, input.length-1);
while(index != k-1){
if(index > k-1)
index = partition(input, 0, index-1);
if(index < k-1)
index = partition(input, index+1, input.length-1);
}
for(int i=0; i<=index; i++)
res.add(input[i]);
return res;
}
public int partition(int[] arr, int left, int right){
int random = (int)(Math.random()*(right - left + 1)) + left;
swap(arr, random, right);
int small = left-1;//小于区 (最开始写错了小于区的初始值!)
int big = right;//大于区
while(left < big){
if(arr[left] < arr[right])
swap(arr, left++, ++small);
else if(arr[left] > arr[right])
swap(arr, left, --big);
else
left++;
}
swap(arr, big, right);
return big;
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Comparator;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<>();
if(k==0)
return res;
if(input==null || input.length==0)
return res;
if(input.length<k)
return res;
PriorityQueue<Integer> pq = new PriorityQueue<>(k, new Comparator<Integer>(){
public int compare(Integer o1, Integer o2){
return o2 - o1;
}
});
for(int i=0; i<input.length; i++){
if(pq.isEmpty() || pq.size()<k)
pq.add(input[i]);
else{
if(input[i]<pq.peek()){
pq.poll();
pq.add(input[i]);
}
}
}
while(!pq.isEmpty()){
res.add(pq.poll());
}
return res;
}
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<>();
if(input == null || input.length==0 || input.length<k || k<1)
return res;
//使用partition,让partition返回小于等于区的边界
int index = partition(input, 0, input.length-1);
while(index != k-1){
if(index < k-1)
index = partition(input, index+1, input.length-1);
else // index > k-1
index = partition(input, 0, index-1);
}
//here, index == k
for(int i=0; i<k; i++)
res.add(input[i]);
return res;
}
/*
进行一次划分后,某个元素处于最终的位置上,该位置的左边都小于等于划分值,右边都大于划分值
*/
public int partition(int[] arr, int left, int right){
int randomIndex = (int)(Math.random()*(right-left+1)+left);
swap(arr, randomIndex, right);//把划分值放到最后
int small = left-1; //小于等于区
while(left < right){ //分成两个区:注意循环终止条件
if(arr[left] <= arr[right])
swap(arr, left++, ++small);
else
left++;
}
swap(arr, small+1, right);//将划分值放到大于区边界
return small+1;//返回划分值的最终索引
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<>();
if(input==null || input.length<k || k<1)
return res;
//selection sort
int min;
for(int i=0; i<k; i++){
min = i;
for(int j=i+1; j<input.length; j++){
if(input[j] < input[min])
min = j;
}
swap(input, i, min);
res.add(input[i]);
}
return res;
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
// 基于partition的方法
//input check
ArrayList<Integer> al = new ArrayList<Integer>();
if(input.length < k)
return al;
//execute
// partition的返回值为0,1,2,...N-1中的一个,返回1表示index为1,index是1的元素坐标有一个元素,所以直接用partition的返回值作为k的话,会有一个问题,就是k是N的时候,需要partition的返回值也是N,但是partition的返回值最大是N-1,此时就会造成partition数组越界
if(k == input.length){
for(int i=0; i<input.length; i++)
al.add(input[i]);
return al;
}
int index = partition(input, 0, input.length-1);
while(index != k){
if(index > k)
index = partition(input, 0, index-1);
if(index < k)
index = partition(input, index+1, input.length-1);
}
for(int i=0; i<index; i++)
al.add(input[i]);
return al;
}
public int partition(int[] input, int lo, int hi){
//注意input只有一个元素的情况, 此时要注意数组索引是否越界
int i=lo, j=hi+1, pivot=input[lo];
while(true){
while(++i <= input.length && input[i] < pivot)
if(i==hi)
break;
while(--j >= 0 && input[j] >= pivot)
if(j==lo)
break;
if(i>=j)
break;
swap(input, i, j);
}
swap(input, lo, j);
return j;
}
public void swap(int[] input, int i, int j){
int temp = input[i];
input[i] = input[j];
input[j] = temp;
}
}