求序列第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.pswp.cn/news/383691.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383691.shtml
英文地址,請注明出處:http://en.pswp.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多進程拷貝文件

學習了mmap以后&#xff0c;實現一個簡單的小程序&#xff0c;進行多個進程對一個文件進行拷貝。 Linux mmap共享內存學習可以參考我的另一篇博客&#xff1a;傳送門 實現思想 我們可以將原來的文件利用mmap分成多個段分別進行傳輸。 實現代碼 #include<stdio.h> #…

斐波那契查找(Fibonacci Search)和折半查找

兩個查找算法都是針對有序數組進行查找&#xff0c;不同點在于分界點的取值不同。 算法介紹 折半查找很簡單&#xff0c;每次與當前區間的中點進行比較&#xff0c;然后決定查找前一部分還是后一部分。 Fibonacci查找利用了Fibonacci序列每一項等于前兩項和的特點進行劃分&a…

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>#…

二分查找的最大比較次數

二分查找很簡單&#xff0c;可是對于一個區間長度為n的數組&#xff0c;最大的比較次數為多少呢&#xff1f; 對于標準的二分查找&#xff0c;我們每次從區間[l,r)中取一個值&#xff0c;和中間值mid(lr)>>1進行比較&#xff0c;然后將數組分為[l,mid) [mid1,r)&#xf…

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;不阻塞也…

快速排序詳解+各種實現方式

快速排序的思想大體來說比較簡單&#xff0c;就是從數組中挑選一個數字當做樞紐&#xff0c;然后將比樞紐大的和比樞紐小的分別放在樞紐的兩邊&#xff0c;再遞歸地對兩邊進行操作&#xff0c;從而進行分治解決問題。平均情況下快速排序是復雜度為O(nlogn)O(nlogn)O(nlogn)&…

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;再從下…