求前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. MVC_防止HttpPost重复提交

    重复提交的场景很常见,可能是当时服务器延迟的原因,如购物车物品叠加,重复提交多个订单.常见的解决方法是提交后把Button在客户端Js禁用,或是用Js禁止后退键等.在ASP.NET MVC 3 Web ...

  2. sql 某字段存储另一个表的多个id值并以逗号分隔,现根据id去中文并拼接同样以逗号分隔

    首先介绍用到的两个函数 charindex(要查找的表达式1,表达式2),返回值为表达式1在表达式2中的下标,未找到则返回0.(sql的下标是从1开始的),例如 select charindex('s ...

  3. python-编码-15

    ascii A : 00000010 8位 一个字节 unicode A : 00000000 00000001 00000010 00000100 32位 四个字节 中:00000000 00000 ...

  4. 初学习Qt的一些感悟

    最近用Qt写了个人项目,有如下心得(可能有不准确): Qt尽管没有扩展C++语法,但是有额外编译链,每个Q_OBJECT类编译的时候会用moc工具生成另一个meta C++类,之后就是标准C++编译流 ...

  5. 《Linux内核设计与实现》读书笔记 1&2

    第一章    Linux内核简介 1.2追寻Linus足迹:linux简介 Linus开发.Linux是类Unix系统.Linux内核也是自由软件. 1.3操作系统和内核简介 操作系统:在整个系统中负 ...

  6. 伪GZCC官网

    <html class="no-js"><head> <meta charset="utf-8"> <meta htt ...

  7. 速读《构建之法》(Build to win)有感

    通过这两天时间,我粗读了<构建之法>这本书.老实说,对于这样四百多页的一本书,刚开始把这样的任务当作是一种负担,然而当我开始真正接触它时却被它幽默有趣的风格所深深吸引,它不同于以往学习的教 ...

  8. CI框架在辅助函数中使用配置文件中的变量

    问题: 现有一个自定义的辅助函数,想要获取配置文件中的配置项(配置文件路径为application/config/config.php) 分析: 辅助函数并不是定义在一个class中,而是很多个可供外 ...

  9. PAT 1002 写出这个数

    https://pintia.cn/problem-sets/994805260223102976/problems/994805324509200384 读入一个自然数n,计算其各位数字之和,用汉语 ...

  10. HDU 2053 Switch Game

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