求前k小的数,一般人的想法就是先排序,然后再遍历,但是题目只是求前N小,没有必要完全排序,所以可以想到部分排序,而能够部分排序的排序算法我能想到的就是堆排序和快排了。

第一种思路,局部堆排序。

  首先,建立一个大小为N的大顶堆,时间复杂度klgk,然后用其余的数和堆顶元素比较,如果小于堆顶元素则与堆顶元素交换,并进行一次调整,时间复杂度(n-k)lgk,然后klgk可以常数级,(n-k)lgk=O(n)。

第二种思路,利用快排的partition。

  只需要稍微修改qsort函数即可,增加判断条件,当partition小于k则快排partition+1到right,如果partition大于k则快排left到partition-1,如果partition等于k,则直接输出数组前k个数,即所求。因为每一轮partition,左部的数都会小于基准数,右部大于基准数 ,所以如果基准下标小于k,说明第k大的数肯定不在基准左部,所以可以缩小搜索条件,直接搜索基准右部,同理基准下标大于k,说明第k大的数肯定不在基准右部,直接搜索基准左部。不过需要注意的一点是qsort中的if(left<right)要改成if(left<right),因为判断partition==k要在下一个递归中。时间复杂度网上证明是O(n)。

public class partitionFindN {
@Test
public void test(){
int[] num = {1,5,9,7,3,4,8,1,6,3,5};
findSmallN(num,8);
} public void findSmallN(int[] num,int n){
Qsort(num,0,num.length-1,n-1);
} public void Qsort(int[] num,int left,int right,int k){
if(left<=right){
int partition = partition(num,left,right);
if(partition==k){
System.out.println("前"+(k+1)+"小的元素为:");
for(int i =0;i<= k;i++){
System.out.print(num[i]+" ");
}
}
else if(partition<k){
Qsort(num,partition+1,right,k);
}
else{
Qsort(num,left,partition-1,k);
}
}
} public int partition(int[] num,int left,int right){
int partition = num[left];
while(left<right){
while(left<right && num[right]>=partition){
right--;
}
swap(num,left,right);
while(left<right && num[left]<=partition){
left++;
}
swap(num,left,right);
}
return left;
} public void swap(int[] num,int m,int n){
int temp = num[m];
num[m] = num[n];
num[n] = temp;
}
}

利用快排partition求前N小的元素的更多相关文章

  1. 树状数组求第k小的元素

    int find_kth(int k) { int ans = 0,cnt = 0; for (int i = 20;i >= 0;i--) //这里的20适当的取值,与MAX_VAL有关,一般 ...

  2. 快排法求第k大

    快排法求第k大,复杂度为O(n) import com.sun.media.sound.SoftTuning; import java.util.Arrays; import java.util.Ra ...

  3. 记录一个基于Java的利用快排切分来实现快排TopK问题的代码模板

    使用快排切分实现快排和TopK问题的解题模板 import java.util.Arrays; public class TestDemo { public static void main(Stri ...

  4. 算法导论-顺序统计-快速求第i小的元素

    目录 1.问题的引出-求第i个顺序统计量 2.方法一:以期望线性时间做选择 3.方法二(改进):最坏情况线性时间的选择 4.完整测试代码(c++) 5.参考资料 内容 1.问题的引出-求第i个顺序统计 ...

  5. 求第k小的元素

    用快排解决: 用快排,一趟排序后,根据基准值来缩小问题规模.基准值的下角标i 加1 表示了基准值在数组中第几小.如果k<i+1,那就在左半边找:如果k>i+1那就在右半边找.当基准值的下角 ...

  6. 隐式Dijkstra:在状态集合中用优先队列求前k小

    这种技巧是挺久以前接触的了,最近又突然遇到几道新题,于是总结了一下体会. 这种算法适用的前提是,标题所述的"状态集合"大到不可枚举(否则枚举就行了qaq) ...

  7. 求第 k 小:大元素

    #include<bits/stdc++.h> using namespace std; void swap_t(int a[],int i,int j) { int t=a[i]; a[ ...

  8. [剑指Offer]39-数组中出现次数超过一半的数字(快排延申,找第k大数同理)

    题目链接 https://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163?tpId=13&tqId=11181&t ...

  9. Hints of sd0061(快排思想)

    Hints of sd0061 Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

随机推荐

  1. 【转】Git版本控制软件从入门到精通学习手册

    GIT 学习手册简介 本站为 Git 学习参考手册.目的是为学习与记忆 Git 使用中最重要.最普遍的命令提供快速翻阅. 这些命令以你可能需要的操作类型划分,并且将提供日常使用中需要的一些常用的命令以 ...

  2. xcode archive 去掉dsym文件和添加dsym文件

    打包慢,让人发狂!!! 所以我们尝试的去掉一些测试时候用不到的东西 比如DSYM: 这DSYM是收集奔溃的.在测试的时候不需要这些东西的所以去掉就好: 项目  Build Settings -> ...

  3. jsp中获取不到servlet的cookie

    今天做登陆,发现jsp中使用document.cookie获取不到servlet生成的cookie,我们可以在浏览器的cookie文件夹中发现,servlet中生成的cookie和jsp中的生成的路径 ...

  4. Redis持久化的两种方式和区别

    该文转载自:http://www.cnblogs.com/swyi/p/6093763.html Redis持久化的两种方式和区别 Redis是一种高级key-value数据库.它跟memcached ...

  5. PAT 1016 部分A+B

    https://pintia.cn/problem-sets/994805260223102976/problems/994805306310115328 正整数A的“D~A~(为1位整数)部分”定义 ...

  6. HDU 2053 Switch Game

    http://acm.hdu.edu.cn/showproblem.php?pid=2053 Problem Description There are many lamps in a line. A ...

  7. Consul vs. Zookeeper

    https://www.consul.io/intro/vs/zookeeper.html 阿里不用zookeeper而是用consul,京东也在用consul.

  8. Activiti 用户手册

    https://tkjohn.github.io/activiti-userguide/

  9. node的cookie-parser和express-session

    let express = require('express'); let cookieParser = require('cookie-parser'); let expressSession = ...

  10. Python——多进程

    进程的实例 # -*- coding:UTF-8 -*- import os import time from multiprocessing import Process #进程 def func( ...