求序列第K大算法总结

参考博客:传送门

在上面的博客中介绍了求序列第K大的几种算法,感觉收益良多,其中最精巧的还是利用快速排序的思想O(n)查询的算法。仔细学习以后我将其中的几个实现了一下。

解法 1:

将乱序数组从大到小进行排序然后取出前K大,总的时间复杂度为O(nlogn)

解法 2:

利用选择排序或交互排序,取出前K大,总的时间复杂度为O(nk)

解法 3:

借鉴快速排序的思想,复杂度近似为O(n)

#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;int kth_number(int *a,int l,int r,int k)
{if(r-l == 1) return a[l];int key=a[l];int index=l;for(int i=l+1;i<r;++i){if(a[i]>=key) continue;else{++index;swap(a[i],a[index]);}}swap(a[index],a[l]);if(r-index == k) return a[index];if(r-index-1 >= k) return kth_number(a,index+1,r,k);else return kth_number(a,l,index,k-r+index);
}

测试程序

#include<cstdio>
#include"Kth_number.h"using namespace std;int main()
{int n,k;const int MAXN=1005;int a[MAXN];printf("n="); scanf("%d",&n);printf("k="); scanf("%d",&k);if(k>n) k=n;printf("please input %d number:\n",n);for(int i=0;i<n;++i)scanf("%d",&a[i]);printf("the %dth number of array is %d\n",k,kth_number(a,0,n,k));return 0;
}

运行结果

在这里插入图片描述

解法 4:

借助堆排序的思想,将前K个数字弹出,复杂度为建立堆的O(4n)加上k次堆排序O(logn)O(4n+klogn)

实现程序

#include<cstdio>
#include<cstdlib>
#include<climits>
#include<algorithm>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<unistd.h>using namespace std;void Adjust(int *a, int n, int i)
{int x = a[i];for(int k = i<<1; k <= n; k = k<<1){if(k+1 <= n && a[k] < a[k+1])++k;if(a[k] > x){a[i] = a[k];i = k;}else{break;}}a[i] = x;
}void MakeHeap(int *a, int n)
{for(int i = n/2;i > 0;--i){Adjust(a, n, i);}
}void HeapSort(int *a,int n,int k,int *ans)
{int m=n-k;for(int i = n; i > m; i--){swap(a[1], a[i]);Adjust(a, i-1, 1);}*ans = a[m+1];
}int main(int argc, char* argv[])
{int n;const int MAXN = 1024;scanf("%d", &n);int a[MAXN] = {0};for(int i = 1; i <= n; ++i){scanf("%d", &a[i]);}int k;scanf("%d", &k);if(k > n) k = n;MakeHeap(a, n);int ans;HeapSort(a, n, k, &ans);printf("ans=%d\n", ans);return 0;
}

测试结果

在这里插入图片描述

解法 5:

维护一个大小为k的小顶堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则弹出堆顶,将当前值插入到堆中。时间复杂度O(4k+nlogk)

实现程序

#include<cstdio>
#include<cstring>using namespace std;void Adjust(int *a,int n,int i)
{int x=a[i];for(int k=i<<1;k<=n;k<<=1){if(k+1<=n && a[k]>a[k+1])++k;if(a[k]<x){a[i]=a[k];i=k;}else break;}a[i]=x;
}
void MakeHeap(int *a,int n)
{for(int i=n/2;i>0;--i){Adjust(a,n,i);}
}
int KthNumber(int *a,int n,int k)
{
//	int *b=new int[k];int b[1024];for(int i=1;i<=k;++i){b[i]=a[i];}MakeHeap(b,k);for(int i=k+1;i<=n;++i){if(a[i]>b[1]){b[1]=a[i];Adjust(b,k,1);}}return b[1];
}int main()
{int n,k;printf("n="); scanf("%d",&n);printf("k="); scanf("%d",&k);
//	int* a = new int[n];int a[1024]={0};for(int i=1;i<=n;++i)scanf("%d",&a[i]);printf("%d\n",KthNumber(a,n,k));
//	delete a;return 0;
}

测试结果

在这里插入图片描述

解法 6:

利用Hash保存数组中元素出现的次数,利用计数排序的思想,线性从大到小扫描中得到结果,时间复杂度为O(n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux网络编程——tcp并发服务器(多线程)

https://blog.csdn.net/lianghe_work/article/details/46504243tcp多线程并发服务器多线程服务器是对多进程服务器的改进&#xff0c;由于多进程服务器在创建进程时要消耗较大的系统资源&#xff0c;所以用线程来取代进程&#xff0c;这样服务处理程序可以较快的创建。据统计&a…

计算机网络【三】物理层数据通信

物理层传输媒介 导向传输媒体&#xff0c;比如光纤和铜线 双绞线&#xff08;屏蔽双绞线STP 五屏蔽双绞线UTP&#xff09;电线扭曲在一起可以降低互相之间的电磁干扰 同轴电缆 (50欧姆的基带同轴电缆&#xff0c;75欧姆的宽带同轴电缆) 10M和100M网络只使用了四根线&#xf…

02_算法分析

02_算法分析 0.1 算法的时间复杂度分析0.1.1 函数渐近增长概念&#xff1a;输入规模n>2时&#xff0c;算法A1的渐近增长小于算法B1 的渐近增长随着输入规模的增大&#xff0c;算法的常数操作可以忽略不计测试二&#xff1a;随着输入规模的增大&#xff0c;与最高次项相乘的常…

Linux网络编程——I/O复用之select详解

https://blog.csdn.net/lianghe_work/article/details/46506143一、I/O复用概述I/O复用概念&#xff1a;解决进程或线程阻塞到某个 I/O 系统调用而出现的技术&#xff0c;使进程不阻塞于某个特定的 I/O 系统调I/O复用使用的场合&#xff1a;1.当客户处理多个描述符&#xff08;…

Linux网络编程——tcp并发服务器(I/O复用之select)

https://blog.csdn.net/lianghe_work/article/details/46519633与多线程、多进程相比&#xff0c;I/O复用最大的优势是系统开销小&#xff0c;系统不需要建立新的进程或者线程&#xff0c;也不必维护这些线程和进程。代码示例&#xff1a;#include <stdio.h> #include &l…

操作系统【二】死锁问题以及处理方法

死锁的概念 死锁&#xff1a;在并发环境下&#xff0c;个进程因为竞争资源而造成的一种互相等待对方手里的资源&#xff0c;导致各进程都阻塞&#xff0c;无法向前推进的现象。 区别&#xff1a; 饥饿&#xff1a;由于长期得不到想要的资源进程无法向前推进的现象。死循环&a…

Linux网络编程——I/O复用之poll函数

https://blog.csdn.net/lianghe_work/article/details/46534029一、回顾前面的selectselect优点&#xff1a;目前几乎在所有的平台上支持&#xff0c;其良好跨平台支持也是它的一个优点select缺点&#xff1a;1.每次调用 select()&#xff0c;都需要把 fd 集合从用户态拷贝到内…

操作系统【一】进程同步和信号量

基本概念 进程异步性特征&#xff1a;各并发执行的进程以各自独立的&#xff0c;不可预知的速度向前推进。 进程同步又称作直接制约关系&#xff0c;他是指为完成某种任务而建立的两个或者多个进程&#xff0c;这些进程因为需要在某些位置上协调他们的工作顺序而产生的制约关…

计算机网络【四】数据链路层基本概念+点到点通信(PPP协议)

数据链路层基本概念 路由器是网络层设备 数据链路层&#xff1a;数据管道&#xff0c;传输的是数据包加上发送地址&#xff0c;接收地址&#xff0c;校验的数据帧 数据链路层的信道类型&#xff1a; 点到点信道&#xff1a;使用一对一的点到点通信方式&#xff08;两个设备…

Linux网络编程——tcp并发服务器(poll实现)

https://blog.csdn.net/lianghe_work/article/details/46535859想详细彻底地了解poll或看懂下面的代码请参考《Linux网络编程——I/O复用之poll函数》 代码&#xff1a;#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#…

Linux网络编程——I/O复用函数之epoll

https://blog.csdn.net/lianghe_work/article/details/46544567一、epoll概述epoll 是在 2.6 内核中提出的&#xff0c;是之前的 select() 和 poll() 的增强版本。相对于 select() 和 poll() 来说&#xff0c;epoll 更加灵活&#xff0c;没有描述符限制。epoll 使用一个文件描述…

操作系统【三】内存管理基础+连续内存分配

内存的基础知识 内存分为按字节编址&#xff08;8位&#xff09;和字编制&#xff08;不同计算机不一样&#xff0c;64位计算机就是64位&#xff0c;即8个字节&#xff09; 相对地址逻辑地址 绝对地址物理地址 从逻辑地址到物理地址的转换由装入解决。 装入的三种方式 绝对…

MSG_PEEK标志

https://blog.csdn.net/aspnet_lyc/article/details/28937229 MSG_PEEK标志可以用来读取套接字接收队列中可读的数据&#xff0c;一些情况会用到它&#xff0c;比如为了避免不阻塞而先检查套接字接收队列中可读的数据长度&#xff0c;再采取相应操作。当然&#xff0c;不阻塞也…

C++的单例模式与线程安全单例模式(懒汉/饿汉)

https://www.cnblogs.com/qiaoconglovelife/p/5851163.html1 教科书里的单例模式我们都很清楚一个简单的单例模式该怎样去实现&#xff1a;构造函数声明为private或protect防止被外部函数实例化&#xff0c;内部保存一个private static的类指针保存唯一的实例&#xff0c;实例的…

计算矩阵的逆和行列式的值(高斯消元+LU分解)

计算矩阵的逆 选主元的高斯消元法 朴素的高斯消元法是将矩阵A和单位矩阵放在一起&#xff0c;通过行操作&#xff08;或者列操作&#xff09;将A变为单位矩阵&#xff0c;这个时候单位矩阵就是矩阵A的逆矩阵。从上到下将A变为上三角矩阵的复杂度为O(n3n^3n3)&#xff0c;再从下…

Linux网络编程——tcp并发服务器(epoll实现)

https://blog.csdn.net/lianghe_work/article/details/46551871通过epoll实现tcp并发回执服务器&#xff08;客户端给服务器发啥&#xff0c;服务器就给客户端回啥&#xff09; 代码如下&#xff1a;#include <string.h>#include <stdio.h>#include <stdlib.h&g…

证明AVL树的上界和下界

对于n个节点的AVL树&#xff0c;其高度最低的时候肯定为叶子节点只在最后一层和倒数第二层的时候。即对于2k−1<n≦2k1−12^k-1< n\leqq 2^{k1}-12k−1<n≦2k1−1的时候下界都为kkk。因此下界为h┌log2(n1)┐−1h\ulcorner log_2(n1)\urcorner-1h┌log2​(n1)┐−1 对…

浅谈dup和dup2的用法

https://blog.csdn.net/u012058778/article/details/78705536一、dup和dup2函数 这两个函数都可以来复制一个现有的文件描述符&#xff0c;他们的声明如下&#xff1a;#include <unistd.h>int dup(int fd);int dup2(int fd, int fd 2); 123 关于dup函数&#xff0c;当我…

C++ cin 实现循环读入

习惯了使用while(~scanf("%d",x)){}来实现循环读入&#xff0c;但是有时候使用泛型编程的时候就必须使用C中的cin&#xff0c;但是当我想要实现循环读入的时候却发现有些困难。 我们可以看一下下面这个简单的例子&#xff1a; #include <iostream>using name…