查詢集合中兩個最大的元素

2021-09-30 09:21:54 字數 2057 閱讀 1523

查詢集合中兩個最大的元素

啟示:我們應該仔細檢查證明過程中是否確實用到了所有的假設;應該設法用更少的假設完成同樣的證明;另外,除非有反例說明已經到達所有可能的證明的邊界,否則我們應該永不滿足。

———polyaand szego[1927]

消除非實質性的假設有時能夠得到更好的演算法,不必要的假設有時意味著證明可能存在錯誤。

問題:已知集合s有n個元素x1,x2,….xn,求其中最大的和第二大的元素。

分析:我們要盡可能的減少比較次數,為簡單起見,設n為2的冪。

分治:把s分成大小為n/2的兩個子集p和q。如果現在直接進行歸納,則假設已知p和q中的最大和第二大的元素,分別記為p1,p2和q1,q2,然後查詢s中的最大和第二大的元素。很明顯,兩次比較足以找到s中的這兩個元素。第一次比較最大數p1和q1,此時得到乙個新的第二大的數,這個數與原來的第二大的數(p或q中的乙個)比較一次,記為所求(比較過程見下圖)。用這種方法得出遞迴關係t(2n)=2t(n)+2及t(2)=1,解得t(n)=3n/2-2。儘管這要優於直接進行的2n-3次比較,但演算法還是可以在改進的。不是每一次找到的最大第二大元素都是有效的,只有到演算法的最後我們才能確定最大元素和第二大元素。

仔細分析上圖的比較,可以看出演算法不再使用q2,故q2的計算是多餘的。如果能精簡這樣的計算,就可以進一步減少比較次數。然而,在p1和q1比較前,我們並不清楚p2和q2中的哪乙個可以不必考慮,如果知道那個子集會「失敗」,那麼就可以在這個子集上用常規的查詢最大數的演算法了,這還能省去不少比較。看來我們已經意識到有些比較可以避免,只是不清楚究竟哪些可以忽略,那應該怎麼做?

技巧:所以把第二大元素的計算推遲到演算法的最後,只保留第二大元素的候選者列表。

歸納(第二次):給定乙個小於n的集合,知道如何找到最大的元素以及第二大元素的乙個「短短的」候選者列表。

短短的到底有多長尚未定義,但在演算法設計過程中,我們會找到乙個合適的值。

演算法:給定大小為n的集合s,把它分為大小為n/2的字跡p和q。由歸納假設可知兩個集合最大的幾個元素是p1和q1,在加上第二大元素的候選者集合cp和cq。首先比較p1和q1,取其中大者。例如p1作為s的最大數,然後捨去cq,因為cq中的所有元素都小於q1,接著再把q1加入cp中。最終我們得到了乙個最大的元素和乙個候選者集合,從中可以直接選出第二大的數。查詢最大數所需的比較次數滿足遞迴關係t(n)=2t(n/2)+1及t(2)=1,解得t(n)=n-1。很容易看到,擴大一倍集合的大小時,我們能在候選者集合中再加入乙個元素,所以lbn足以滿足候選者集合大小的需要。於是查詢第二大元素需要lbn-1次額外比較,因而總比較次數為n-1+lbn-1,恰為最可能的次數。n為2的冪時的歸納假設如下:

歸納(第三次):給定乙個小於n的集合,知道如何求出最大的元素和第二大的元素的候選者集合,這個集合自多不超過lbn個元素。

vector& get2max(int *arr,int len,int &max,vector&candidate)

else if(len == 2)

else

} int p1,q1;

vector&candidate1 = *new vector;

vector&candidate2 = *new vector;

//p子集中的候選者

candidate1 = get2max(arr,len/2,p1,candidate1);

//q子集中候選者

candidate2 = get2max(arr+len/2,len - len/2,q1,candidate2);

if(p1 > q1)

else if(p1 == q1)

else }

void get2max(int *arr, int len)

cout<

總結:如何改進乙個演算法,首先要看到這個演算法的缺點,有時候在腦子裡面執行一遍這個程式,缺點就暴露出來了。所以有必要檢查是否存在對最終結果不起作用的部分,這些部分往往可以被刪除,即使不能被刪除,也可以用更簡單、效率更高的運算代替。

分治演算法會產生一些中間結果,並不是這些中間結果都對我們的最終結果有所幫助。

查詢集合中兩個最大的元素

查詢集合中兩個最大的元素 啟示 我們應該仔細檢查證明過程中是否確實用到了所有的假設 應該設法用更少的假設完成同樣的證明 另外,除非有反例說明已經到達所有可能的證明的邊界,否則我們應該永不滿足。polyaand szego 1927 消除非實質性的假設有時能夠得到更好的演算法,不必要的假設有時意味著證...

查詢集合中兩個最大的元素

程式設計之美的中的課後習題 問題 已知集合s有n個元素x1,x2,xn,求其中最大的和第二大的元素。1 樸實的遍歷尋找。尋找最大數的比較次數為n 1,第二大為n 2次,總次數2n 3 2 分治法。分析 我們要盡可能的減少比較次數,為簡單起見,設n為2的冪。分治 把s分成大小為n 2的兩個子集p和q。...

C 判斷兩個集合中的元素是否相等

今天在寫介面時,需要根據當前傳入的集合資料,和上次傳入的集合資料是否相同,做出不同的邏輯處理.如果直接根據等號進行比較,是比較的記憶體位址,因為兩次傳入,有其中乙個是new建立的,所以肯定不相等。可以使用sequenceequal這個方法,非常實用 demo list long nums newli...