演算法導論9 1 1找第二小的元素

2021-09-25 14:45:55 字數 3031 閱讀 7983

2.演算法實現:

3、總結

做以下斷言:無論採用何種比較演算法,在尋找最小元素的過程中,第二小的元素一定與最小元素做過比較。

顯然,因為第二小的元素直到遇到最小元素前,一定會勝出進入下一輪。如果最小元素沒有與第二小元素相比較,則無法得出該元素是最小的關係。

因此,要想是我們找到最小元素的比較次數最少,就需要在尋找最小元素的過程中與最小元素發生比較的次數盡量的少。

由於每次我們只能取兩個元素進行比較,從而考慮每一輪將我們比較元素兩兩比較,較小的元素進入下一輪(如比較元素有奇數個,落單的直接進入下一輪),這樣比較所得的最小元素比較過的元素是最少的(每輪只有乙個)。

我們將比較過程轉化為二叉樹(以陣列 [7,8,1,3,4,5,9]為例):

其中,除了葉節點外,每個結點都是一次比較的結果。因此該演算法中,比較次數為樹中度為2的結點數。根據二叉樹的性子可以得出比較次數為 n−1

n-1n−

1 (二叉樹:度為2的結點數=葉子葉子結點數-1)。可以看出樹的每一層只有乙個結點與最小元素比較,達到了下界,因此是最優的。

這裡的 n−1

n-1n−

1 次比較下界還有另外的思路。可以把每個元素看成乙個集合。集合中用最小元素代表這個集合。初始狀態下 n

nn個點都是單獨的集合,比較後相當於把集合做合併。合併後用最小值代表這個集合。那麼初始狀態下的 n

nn 個集合,至少經過 n−1

n-1n−

1 次合併才能得到1個集合。

可以看出,與最小元素比較的次數為樹高h-1(根節點的高度為1)。有因為葉節點數個數為n。從而有: n≤2

h−1n \leq 2^

n≤2h−1

,故有 h−1

=⌈lg

n⌉h-1 = \lceil lg n \rceil

h−1=⌈l

gn⌉,即與最小元素比較的次數至少為 ⌈lg

n⌉\lceil lg n \rceil

⌈lgn⌉。

從這 ⌈lg

n⌉\lceil lg n \rceil

⌈lgn

⌉個元素中找到的最小元素即是第二小的元素。最壞情況下第二小元素第一輪遇到最小元素被淘汰,從而在尋找最小元素的過程中,我們無法得到其他元素與第二小元素比較大小關係。這種情況下,要在 ⌈lg

n⌉\lceil lg n \rceil

⌈lgn

⌉個元素中找到最小元素需要 ⌈lg

n⌉−1

\lceil lg n \rceil - 1

⌈lgn⌉−

1次比較。

綜上:最壞情況下,要找到第二小的元素所需的比較次數為 n+⌈

lgn⌉

−2n + \lceil lg n\rceil -2

n+⌈lgn

⌉−2 次比較。

根據上面的解釋。我們其實只要找到最小元素,然後在最小元素比較過程中比較過的元素記錄下來,然後我們在這堆元素(上面證明共⌈lg

n⌉\lceil lg n\rceil

⌈lgn

⌉個)中找最小元素即可。

具體實現:對於每乙個元素,採用陣列或鍊錶的結構,每次比較後勝出的元素記錄與它比較的元素在原陣列的下標,同時自身進入下一輪的比較,根據上面的圖可知,每經過一輪比較,元素被篩選掉一半,直至最終僅剩乙個元素時,它就是最小元素,返回與它比較元素的元素集合。最終在該集合中尋找第二小元素。

#include

#include

#include

#include

#include

using

namespace std;

const

int inf=

0x3f3f3f3f

;class

solution);

}static vector<

int>

findsmallestandcollection

(const vector<

int>

& vec,vector<

int>

* paths)

return paths[winnerindex[0]

];//最終剩乙個返回對於的path

}static

intfindsecondsmallest

(const vector<

int>

& vec,vector<

int>

*paths)

}return smallest2;

}static vector<

int>

compareandstore

(const vector<

int>

&arr,

const vector<

int>

&winnerindex,vector<

int>

* paths)

for(

int i=

1;i)else

solution::cnt++

;//比較次數+1

}return ret;}}

;int solution::cnt=0;

void

showtopten

(vector<

int>

&vec)

intmain()

該演算法主要注重比較次數,但是空間複雜度不樂觀(儲存比較路徑),時間複雜度為 o(n

)o(n)

o(n)

。適合於那種一次比較需要耗費大量時間的值。下面有兩篇我解決該題參考的部落格。

參考部落格

只涉及證明:

部落格1:

包括證明和演算法實現(python)

部落格2:演算法導論/2015-12/9.1-1-second_smallest_element.html

求第二小元素演算法

求第二小元素的時間複雜度是 n 使用暴力求解和該演算法的時間複雜度都是 n 該演算法只是把最壞情況比較次數從2n 32n 3 2n 3 次降低到n lgn 2n lceil lgn rceil 2 n lgn 2。取兩個數作為最小元素和第二小元素,然後依次取剩下的元素和現有的最小元素 第二小元素作比...

演算法導論第二章

插入排序原始碼 1 include 2 include 3 4using namespace std 56 void insert sort inta 7 17 a i 1 key 18 19 2021 intmain 22view code 逆序輸出 1 include 2 include 3 4...

演算法導論9 1 1習題解答 二叉樹

clrs 9.1 1 演算法思想 1.將陣列中的元素分組,每組兩個元素,然後比較每組中的兩個元素得到最小值,重新得到包含原來一半元素的陣列,繼續重複上述過程,那麼最後乙個元素必然為最小值。如圖所示,陣列為 2.上述過程形成的是乙個二叉樹,其中葉子節點都為陣列元素,非葉子節點剛好4個,這是二叉樹的性質...