目录
题目1. 最小的k个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
解法
- 默写快排
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<Integer>();
if( k<=0 ||k> input.length ) return res;
int lo = 0, hi = input.length-1;
sort(input,lo,hi);
for(int i = 0; i<k; i++)
res.add(input[i]);
return res;
}
private static void sort(int [] input, int lo, int hi){
if(hi<=lo) return;
int pat = partition(input, lo, hi);
sort(input,lo, pat-1);
sort(input,pat+1, hi);
}
private static int partition(int [] input, int lo, int hi){
int v = input[lo];
int i = lo, j = hi+1;
while(i<=hi&&j>=0){
while(input[++i]<v)
if(i == hi) break;
while(input[--j]>v)
if(j == lo) break;
if(i>=j) break;
int temp = input[i];
input[i] = input[j];
input[j] = temp;
}
int temp = input[lo];
input[lo] = input[j];
input[j] = temp;
return j;
}
}
2. 在快排的基础上减小时间复杂度
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<Integer>();
if( k<=0 ||k> input.length ) return res;
int lo = 0, hi = input.length-1;
sortKsmall(input,k);
for(int i = 0; i<k; i++)
res.add(input[i]);
return res;
}
private static void sortKsmall(int [] input, int k){
int lo = 0, hi = input.length-1;
while(hi>lo){
int pat = partition(input, lo, hi);
if(pat == k) break;
if(pat>k) hi = pat-1;
else lo = pat+1;
}
}
private static int partition(int [] input, int lo, int hi){
int v = input[lo];
int i = lo, j = hi+1;
while(i<=hi&&j>=0){
while(input[++i]<v)
if(i == hi) break;
while(input[--j]>v)
if(j == lo) break;
if(i>=j) break;
int temp = input[i];
input[i] = input[j];
input[j] = temp;
}
int temp = input[lo];
input[lo] = input[j];
input[j] = temp;
return j;
}
}
利用了partition(),partition()的作用是把数组分成两拨,左边的小于input[lo],右边的大于input[lo]。但是这两拨没有被排序。
题目2. 寻找第K大的数
题目描述
有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
解法
第K大也就是从小到大排序的倒数第K个数字。即寻找排序后索引为N-K的数字。
故这道题目直接转化成了求最小的前N-K个数。
import java.util.*;
public class Solution {
public static void exch(int[] a, int lo, int hi){
int temp = a[lo];
a[lo] = a[hi];
a[hi] = temp;
}
public static int partition(int[] a, int lo, int hi){
int v = a[lo];
int i = lo;
int j = hi+1;
while(i<j){
while(a[++i]<v) {
if(i == hi) break;
}
while(a[--j]>v) {
if(j == lo) break;
}
if(i>=j) break;
exch(a,i,j);
}
exch(a,lo,j);
return j;
}
//从小到大排序的前k位
private static void sortKsmall(int [] input, int k){
int lo = 0, hi = input.length-1;
while(hi>lo){
int pat = partition(input, lo, hi);
if(pat == k) break;
if(pat>k) hi = pat-1;
else lo = pat+1;
}
}
public int findKth(int[] a, int n, int K) {
// write code here
int t = 0;
int lo = 0;
int hi = n-1;
sortKsmall(a,n-K); //第K大也就是正数索引位于n-K的元素
return a[n-K];
}
}