尋找第K大的數字

尋找第k大的數字,有很多方法,最基本的就是將數組按照從大到小的順序排列,找出第k個元素即可。但是這種方法的時間復雜度為o(nlog(n)),我們還能找到更好地方法。下面我們將介紹另外兩種辦法,一種是基于快排Partition的方法,一種是基于partial_sort的方法。

基于快排partition的查找法

利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分為兩部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。這時有兩種情況:

  1. Sa中元素的個數小于k,則Sb中的第k-|Sa|個元素即為第k大數;
  2. Sa中元素的個數大于等于k,則返回Sa中的第k大數。時間復雜度近似為O(n)

遞歸法

#include <iostream>using namespace std;//快速排序的劃分函數
int partition(int data[],int i,int j)
//將>=x的元素換到左邊區域
//將<=x的元素換到右邊區域
{if(data==NULL||i<0)throw std::exception("invalued parameter");int index = i+rand()%(j-i+1);//生產隨機數int pivot=data[index];swap(data[i],data[index]);while(i<j){while(i<j&&pivot>=data[j]){j--;}if (i<j){data[i++]=data[j];}while(i<j&&pivot<=data[i]){i++;}if (i<j){data[j--]=data[i];}}data[i]=pivot;return i;
}//線性尋找第k大的數,遞歸法
int random_select(int a[],int l,int r,int k)
{if(k>(r-l+1)||k<1)//k應該在[1,r-l+1]之間throw std::exception("invalued k");int i,j;if (l == r) //遞歸結束{return a[l];}i = partition(a,l,r);//劃分j = i-l+1;//距開始的長度,i為第j大的數字if(k == j) //遞歸結束,找到第K大的數return a[i];if(k < j){return random_select(a,l,i-1,k);//遞歸調用,在前面部分查找第K大的數}elsereturn random_select(a,i+1,r,k-j);//遞歸調用,在后面部分查找第K大的數
}int main()
{int a[]={1,2,3,4,6,6,7,8,10,10};cout<<random_select(a,0,9,1)<<endl;cout<<random_select(a,0,9,5)<<endl;return 0;
}

循環法

#include <iostream>using namespace std;//快速排序的劃分函數
int partition(int data[],int len, int i, int j)
//將>=x的元素換到左邊區域
//將<=x的元素換到右邊區域
{if (data == NULL ||len<=0|| i < 0||j>=len)throw std::exception("invalued parameter");int index = i + rand() % (j - i + 1);//生產隨機數int pivot = data[index];swap(data[i], data[index]);while (i < j){while (i < j&&pivot >= data[j]){j--;}if (i < j){data[i++] = data[j];}while (i < j&&pivot <= data[i]){i++;}if (i<j){data[j--] = data[i];}}data[i] = pivot;return i;
}//線性尋找第k大的數,循環法
int random_select(int a[],int len, int k)
{if (a == NULL || len <= 0 || k > len || k <= 0){throw std::exception("invalued parameter");}int i = 0;int j = len - 1;int index = partition(a, len, i, j);while (index+1!= k){if (index+1> k){index = partition(a, len, i, index - 1);}else{index = partition(a, len, index + 1, j);}}int result = a[k-1];return result;}int main()
{int a[] = { 1, 2, 3, 4, 6, 6, 7, 8, 10, 10 };cout << random_select(a,10, 1) << endl;cout << random_select(a, 10,3) << endl;return 0;
}

上面兩種辦法均是基于partiton的方法,實際上在C++ STL中也有一個實現查找第k大元素的方法:nth_element.

nth_element

nth_element用于排序一個區間,它使得位置n上的元素正好誰全排序情況下的第n個元素,而且,當nth_element返回的時候,所有按照全排序規則排在位置n之前的元素也都排在位置n之前,按照全排序規則排在n之后的元素全都排在位置n之后。
所以,我們使用nth_element既可以尋找最好的前k個元素,也可以尋找第k大元素。

先看示例:

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{int a[10] = { 8, 9, 1, 2, 4, 3, 5, 6, 7, 10 };nth_element(a, a + 5, a + 10, std::greater<int>());cout << "數組中的中間元素是" << a[5] << endl;nth_element(a, a, a + 10, std::greater<int>());cout << "數組中第1大元素為" << a[0] << endl;nth_element(a, a + 1, a + 10, std::greater<int>());cout << "數組中第2大元素是" << a[1] << endl;
}

結果為:

數組中的中間元素是5
數組中第1大元素為10
數組中第2大元素是9
請按任意鍵繼續. . .

使用說明:

default (1) 
template <class RandomAccessIterator>void nth_element (RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last);
custom (2)  
template <class RandomAccessIterator, class Compare>void nth_element (RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last, Compare comp);

default (1) 使用‘<’作為比較符
custom (2) 可以指定比較運算
nth:實際指的是nth+1大(小)元素,也就是如果你要找前20個最大的,nth=19.

基于partial_sort的查找法

用O(4*n)的方法對原數組建最大堆,然后pop出k次即可。時間復雜度為O(4*n + k*logn)
在C++ STL中同樣有一個部分排序的函數就是partial_sort。
用法:

default (1) 
template <class RandomAccessIterator>void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last);
custom (2)  
template <class RandomAccessIterator, class Compare>void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last, Compare comp);

default (1) :使用‘<’作為比較符
custom (2) :可以指定比較運算
middle:將前middle個元素排序,比如說我們要找到前10個最小的元素,而且從小到大排列,這時可以使用partial_sort,middle=10.
注意
partial_sort與上面的nth_element相比,需要對前面最好的n個元素排序,而nth_element只需要找到前面最好的n個元素就可以,不需要知道順序。
而且關于第二個參數的使用上截然不同:partial_sort使用第1個和第2個迭代器指明一段需要排序的區間,根據STL關于區間的定義,第2個參數應該是目標區間外的第一個元素(比如widgets.begin()+20實際指的是第21個元素),而nth_element則使用第2個參數標識出容器中的某個特定位置(比如widgets.begin()+19實際指的是第20個元素)
詳細情況請參考:《理解你的排序操作[(stable_sort,sort,partial_sort,nth_element,stable_partition,partition)》
因此我們可以先部分排序,再直接取第k個元素即可。

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{int a[10] = { 8, 9, 1, 2, 4, 3, 5, 6, 7, 10 };partial_sort(a, a + 6, a + 10, std::greater<int>());cout << "數組中的中間元素是" << a[5] << endl;partial_sort(a, a + 2, a + 10, std::greater<int>());cout << "數組中第1大元素為" << a[0] << endl;partial_sort(a, a + 3, a + 10, std::greater<int>());cout << "數組中第2大元素是" << a[1] << endl;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259216.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259216.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259216.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(12)MSP430F5529 常用內置函數和一些說明

&#xff08;1&#xff09; MSP430F5529支持最高工作頻率為25MHZ&#xff0c;也就是說你通過 鎖相環倍頻來提高系統運行速度是有一個限制的&#xff0c; 最高只能到25MHZ&#xff08;再高沒意思了&#xff09;。 &#xff08;2&#xff09;幾個重要的內聯函數 &#xff08;內聯…

從零開始學android編程_android初學者的入門秘籍

大概是去年年底開始接觸android原本是學習嵌入式的我&#xff0c;領導讓我看看能不能搞一下這個android APP。一開始的我懵逼得很。。。這android APP 不是得用java寫嗎&#xff1f;&#xff1f;&#xff1f; 現在我看網上說比較多還是用kotlin&#xff0c;沒去學。。。好家伙&…

修改了sql默認路徑無法登錄服務器,PostgreSQL錯誤'無法連接到服務器:沒有這樣的文件或目錄'...

像其他一些人一樣,當我在我的項目中運行rake db:migrate或者甚至為我的Ruby on Rails 3.2應用程序嘗試大多數數據庫任務時,我收到此錯誤.PGError(無法連接到服務器:沒有這樣的文件或目錄.服務器是否在本地運行并接受Unix域套接字上的連接"/tmp/.s.PGSQL.5432"&#x…

QMarkDowner編譯

第一次完整的編譯一個工程。哈哈 記錄一下 準備環境 我的環境是win7 x64, python2.7.5 x64的。 python 3.x的我沒試過,有需要的朋友可以試一下。 安裝python2.7.5 x64 確保將安裝路徑加入到Path中 PyQt4 啊 我的環境是win的 當然要下win版 (PyQt4-4.10.3-gpl-Py2.7-Qt4.8.5-x6…

C++ STL的查找算法

假設你有一個序列容器&#xff0c;或者有一對迭代器標識了一個區間,現在你希望在容器中查找一些信息&#xff0c;這樣的查找工作如何進行呢&#xff1f;你的選擇往往是&#xff1a; count,count_if,find,find_if,binary_search,lower_bound,upper_bound,equal_range.該如何選擇…

習題七

umask 022 &#xff0c;請描述該命令的含義創建目錄時默認的權限為&#xff1a;755 rwxr-xr-x創建文件時默認的權限為&#xff1a;644 rw-r--r--note:創建文件的默認權限是拿掉了X 所以最大為666&#xff0c;而目錄最大為777 umask NUM 就是去掉相應的權限轉載于:https://blo…

web中的cookie管理

本篇是以JSP為背景介紹&#xff0c;但是在web開發中也是相同的原理。 什么是cookie 由于http是一種無狀態的協議&#xff0c;因此服務器收到請求后&#xff0c;只會當做一次新的請求。即便你重復發送了1000次同樣的請求&#xff0c;這1000次都屬于獨立的請求。 這樣顯然效率很低…

unity怎么設置游戲頁面_杭州有沒有正規的unity游戲開發培訓機構?

現在Unity游戲開發是個火熱的行業&#xff0c;薪資待遇比較高&#xff0c;未來的發展方向和前景也比較不錯&#xff0c;很多人也都想成為專業Unity游戲開發工程師&#xff0c;學習Unity游戲開發已經成為很多追求更好就業前景的人的選擇。學習專業、系統的Unity游戲開發知識并達…

VC++ 使用attributes定義接口

1.定義預處理命令_ATL_ATTRIBUTES 2.在一個全局的Cpp文件里面配置module的attribute [module(dll, uuid "{3845951F-15B8-4286-8E7D-E9D4F5C7B6CE}", name "TestApp")]3.定義接口 [object,uuid("9F414A8A-1D5E-4aff-A60E-CFD65155ABB6"),dual,…

h3c 虛擬服務器 下一跳,H3CNE 312題和313題 直連路由靜態路由的下一跳問題

321.在MSR 路由器上看到路由表里有如下顯示&#xff1a; Destination/Mask Proto Pre Cost NextHop Interface 127.0.0.0/8 Direct 0 0 127.0.0.1 InLoop0 127.0.0.1/32 Direct 0 0 127.0.0.1 InLoop0 192.168.96.0/19 Direct 0 0 192.168.120.153 S6/0 那么關于目的地321.在MS…

C++成員變量的初始化順序問題

先來看兩道題&#xff1a; // count algorithm example #include <iostream> // std::cout #include <algorithm> // std::count #include <vector> // std::vector using namespace std; class A { public:A() { cout << "in A()&q…

Knockout.Js案例一Introduction

在這第一個教程中,您將體驗的一些基本知識構建的web UI Model-View-ViewModel使用knockout.js(MVVM)模式。案例1&#xff1a;添加:data-bind <p>First name: <strong data-bind"text:firstName">1</strong></p><p>Last name: <stro…

C#注冊表常用操作

1&#xff1a;加鍵 改值 Microsoft.Win32.RegistryKey Key Microsoft.Win32.Registry.CurrentUser.CreateSubKey( "Software\Microsoft\Internet Explorer\Main"); Key.SetValue( "Window Title" , value ); Key.Close(); …

谷歌瀏覽器外貿版_做外貿快兩個月,沒有單怎么辦?

Hello 大家好&#xff0c;我是Jack。今天給大家更新一篇在知乎看到的外貿問題&#xff1a;做外貿快兩個月&#xff0c;沒有單怎么辦?外貿這個話題在知乎算是小眾話題了&#xff0c;相比較于職場&#xff0c;英語學習&#xff0c;國際政治&#xff0c;IT等&#xff0c;這些話題…

React Native通信機制詳解

http://blog.cnbang.net/tech/2698/ React Native是facebook剛開源的框架&#xff0c;可以用javascript直接開發原生APP&#xff0c;先不說這個框架后續是否能得到大眾認可&#xff0c;單從源碼來說&#xff0c;這個框架源碼里有非常多的設計思想和實現方式值得學習&#xff0c…

C++11系列學習之四----auto

在哪些情況下要申明類型&#xff1a; 定義變量類型 函數返回值&#xff0c;函數參數 表達式返回變量類型 auto關鍵字原理 在定義變量的時候必須申明類型&#xff0c;c是強語言類型&#xff0c;在編譯階段需要知道類型&#xff0c;這樣的好處是程序效率更高&#xff0c;而…

windows 自動copy遠程服務器文件

net use h: \\123.45.67.000\T1dbbackup 123456/user:administrator ------遠程服務器IP123.45.67.000 。T1dbbackup&#xff1a;共享文件夾 。 h :映射到本機的盤符。 用戶名&#xff1a;administrator&#xff0c;密碼&#xff1a;123456copy h:\*.* f:\T1DB ------復…

eclipse 不能切換輸入法

按了AltShift鍵&#xff1f;再按一次把EN切換成CN&#xff0c;然后再CtrlShift就可以切換輸入法轉載于:https://www.cnblogs.com/jiayonghua/p/3413827.html

excel打開2個獨立窗口_謝楠稱女性獨立的不是錢是心 謝楠與吳京婚后生育2個兒子...

近日&#xff0c;在綜藝節目《幸福三重奏》 三日談妻子篇中&#xff0c;謝楠被問到如何看待獨立女性時&#xff0c;反問記者會不會問吳京同樣的問題&#xff1b;隨后回答道&#xff0c;女性獨立的不是錢&#xff0c;而是你的心&#xff1b;楠姐的回答超級霸氣了&#xff0c;你們…

C++11系列學習之五-------decltype

使用場景 在C中經常要用到很長的變量名&#xff0c;如果已經有變量和你將使用的變量是一個類型&#xff0c;即可使用decltype關鍵字 來申明一樣的類型變量。 decltype原理 返回現有變量類型&#xff0c;decltype是一個關鍵字&#xff0c;而不是一個函數&#xff0c;這有啥區別…