1、排序
把输入的n个整数排序,然后取前k个数;
时间复杂度:O(nlogn)
2、Partition
通过partition找到第k大的数,它的左边就是前k小的数;
时间复杂度:O(n)
3、最大堆
构建k个整数的最大堆数据结构,然后将剩余n-k个整数依次与堆顶比较,大则抛弃,小则删除堆顶并插入,最后的最大堆就是最小的k个整数;
堆是基于二叉树来实现的,因此插入和删除操作都在O(logk)时间内完成。在代码中可以通过STL中的容器来实现,如set,multiset,priority_queue等,都是基于红黑树实现的,所以是排序的。
时间复杂度:O(nlogk)
完整java代码参考如下:
package chapter5;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class P209_KLeastNumbers {
public static int partition(int[] arr,int l,int r){
if(l>=r) return -1;
int less=l-1;
int more=r;
int index=l;
while (indexarr[r]){
swap(arr,--more,index);
}else {
index++;
}
}
swap(arr,more,r);
return more;
}
public static void swap(int[] a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
public static int[] findKth(int [] arr,int k){
if(arr==null||arr.lengthk-1){
end=index-1;
index=partition(arr,start,end);
}else{
start=index+1;
index=partition(arr,start,end);
}
}
int[] res=new int[k];
for(int i=0;ik-1){
hi=index-1;
index=partition(nums,lo,hi);
}else {
lo=index+1;
index=partition(nums,lo,hi);
}
}
return nums[k-1];
}
public static class MyComparator implements Comparator{
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;//将先前Integer中的自然排序(从小到大)反过来,实现从大到小;
}
}
//解法二:不改变原始数组,使用优先队列,时间复杂度O(nlogk),适合海量数据
public static int[] findKth2(int [] arr, int k) {
if(arr == null || k > arr.length || k<=0) return null;
//优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)
//元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator,类似于C++的仿函数)
PriorityQueue maxQueue = new PriorityQueue(new MyComparator());
//PriorityQueue的peek()和element操作是常数时间,add(), offer(), 无参数的remove()以及poll()方法的时间复杂度都是log(N)。
for(int i =0;i
与快排相关的java实现如下:
//最重要就是partition函数的实现
public class quiksort {
public static int partition(int[] nums,int lo,int hi){
//将数组切分为a[lo...i-1],a[i],a[i+1...hi]
int i=lo,j=hi+1;//左右扫面指针
int v=nums[lo];//切分元素
while (true){
//扫描左右,检查扫描是否结束并交换元素
while (less(nums[++i],v)) if(i>=hi) break;
while (less(v,nums[--j])) if(j<=lo) break;
if(i>=j) break;
swap(nums,i,j);
}
swap(nums,lo,j);//将v=nums[j]放入正确的位置
return j;//a[lo...j-1]<=a[j]<=a[j+1...hi]达成
}
public static boolean less(int a,int b){
if(ak-1){
hi=index-1;
index=partition(nums,lo,hi);
}else {
lo=index+1;
index=partition(nums,lo,hi);
}
}
for(int i=0;ik-1){
hi=index-1;
index=partition(nums,lo,hi);
}else {
lo=index+1;
index=partition(nums,lo,hi);
}
}
return nums[k-1];
}
public static void sort(int[] nums){
sort(nums,0,nums.length-1);
}
public static void sort(int[] nums,int lo,int hi){
if(lo>=hi) return;
int index=partition(nums,lo,hi);//用partition函数切分
sort(nums,lo,index-1);//将左半部分a[lo...j-1]排序
sort(nums,index+1,hi);//将右半部分a[j+1...hi]排序
}
public static void main(String[] args){
int k=4;
int[] n={4,5,1,6,2,7,3,8};
int[] o=new int[k];
// findKth(n,o,k);
// System.out.println(findKthLargest(n,k));
sort(n);
for(int num:n){
System.out.println(num);
}
}
}
利用java的PriorityQueue(最大堆方法)来解决,代码如下:
package Sort;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class getleastnumber {
//解法二:不改变原始数组,使用优先队列,时间复杂度O(nlogk),适合海量数据
public static ArrayList GetLeastNumbers_Solution(int [] input, int k) {
ArrayList result = new ArrayList<>();
if(input == null || k > input.length || k<=0) return result;
//优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)
//元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator,类似于C++的仿函数)
PriorityQueue maxQueue = new PriorityQueue(k,new Comparator(){//使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。
@Override
public int compare(Integer o1,Integer o2){
return o2.compareTo(o1);//将先前Integer中的自然排序(从小到大)反过来,实现从大到小;
}
});
//PriorityQueue的peek()和element操作是常数时间,add(), offer(), 无参数的remove()以及poll()方法的时间复杂度都是log(N)。
for(int i =0;i input[i]){
Integer temp = maxQueue.poll();//必须先去除队列头部的数据,以保证队列长度
temp = null;
maxQueue.offer(input[i]);
}
}
for(Integer i : maxQueue){
result.add(i);
}
return result;
}
public static void main(String[] args){
ArrayList result = new ArrayList<>();
int[] nums={4,5,1,6,2,7,3,8};
int k=4;
result=GetLeastNumbers_Solution(nums,k);
for(int num:result){
System.out.println(num);
}
}
}
基于排序,参考代码如下:
class Solution {
public:
vector GetLeastNumbers_Solution(vector input, int k) {
vector n;
if(k > input.size()) return n;
sort(input.begin(), input.end());
while(k){
n.insert(n.begin(), input[k-1]);
k--;
}
return n;
}
};
基于Partition,参考代码如下:
int Partition(int* numbers,int start,int end){
int key=numbers[start];
int i=start;
int j=end;
while(i=key)
--j;
if(in || n<=0 || k<=0)
return;
int start=0;
int end=n-1;
int index=Partition(input,start,end);
while(index!=k-1){
if(index>k-1){
end=index-1;
index=Partition(input,start,end);
}
else{
start=index+1;
index=Partition(input,start,end);
}
}
for(int i=0;i
基于最大堆,参考代码如下:
typedef multiset > inSet;
typedef multiset >::iterator setIterator;
void GetLeastNumbers_1(const vector &data,inSet &leastNumbers,unsigned int k){
leastNumbers.clear();
if(k<1 || data.size()::const_iterator it=data.begin();
for(;it!=data.end();it++){
if(leastNumbers.size()
a.功能测试(输入的数组中有相同的数字;输入的数组中没有相同的数字)。
b.边界值测试(输入的k等于1或者等于数组的长度)。
c.特殊输入测试(k小于1;k大于数组的长度;指向数组的指针为nullptr)。
http://www.cnblogs.com/AndyJee/p/4672862.html