《演算法導論》摘記 經典演算法題集錦

2022-05-06 14:42:08 字數 3682 閱讀 9074

分治策略

diogenes教授有n個被認為是完全相同的vlsi晶元,原則上它們是可以互相測試的。教授的測試裝置一次可測二片,當該裝置中放有兩片晶元時,每一片就對另一片作測試並報告其好壞。乙個好的晶元總是能夠報告另一片的好壞,但乙個壞的晶元的結果是不可靠的。這樣,每次測試的四種可能結果如下:

a晶元報告         b晶元報告     結論

b是好的          a是好的      都是好的,或都是壞的

b是好的          a是壞的      至少一片是壞的

b是壞的          a是好的      至少一片是壞的

b是壞的          a是壞的      至少一片是壞的

q:1.證明如果超過n/2個晶元是壞的,使用任何基於這種逐對檢測操作的策略,教授都不能確定哪些晶元是好的。

2.如果超過n/2個晶元是好的,如何o(n)找出所有好的晶元?

解:對於問題2,只需找出1個好的晶元,就能確定所有的晶元的好壞。

粗暴的方法是拿乙個晶元與其他所有晶元配對,因為好的比壞的多,就可以根據多的確定該晶元的好壞,直到找到乙個好晶元為止。複雜度是o(n2)的。同時也說明了q1(否則無法確定好壞)

o(n)怎麼做?遞迴縮小問題規模。

假設有偶數個晶元。兩兩配對,有a對檢測結果為都是好的,b對檢測結果為一好一壞,c對檢測結果為都是壞的。

取a對中每對的任意乙個晶元,組成a個晶元的子問題。易證明該子問題依然滿足好的晶元數量多於壞的晶元。(因為b+c對中壞的 >=好的)

如果有奇數個晶元。兩兩配對,有a對檢測結果為都是好的,b對檢測結果為一好一壞,c對檢測結果為都是壞的。還有乙個零頭。

1.如果零頭是壞的,則a對中好的晶元 >壞的晶元,用a對去檢測零頭,發現有一半以上的檢測結果是壞的,反言之 小於一半的檢測結果是好的。

2.如果零頭是好的,則a對中好的晶元 >=壞的晶元,用a對去檢測零頭,發現大於等於一半的檢測結果是好的。

根據結果判斷零頭是好是壞。如果是1,把零頭棄掉;如果是2,把零頭加進來,這樣該子問題依然滿足好的晶元數量多於壞的晶元。

如此遞迴縮小問題規模,每次規模至少減半。

找出乙個好零件的時間t1(n) = t1(n/2)+o(n) = o(n),

找出其他好零件的時間t2(n) = n−1 =o(n),

所以總的時間t(n)=o(n)。

view codet1

(n)=

t1(n

/2)+

o(n)

=o(n

)'>t2(

n)=n

−1=o

(n)'>t(n

)=o(

n)'>概率分析和隨機演算法t1

(n)=

t1(n

/2)+

o(n)

=o(n

)'>t2(

n)=n

−1=o

(n)'>t(n

)=o(

n)'>1.生日悖論

關於如何卡字串hash

(n)=

t1(n

/2)+

o(n)

=o(n

)'>t2(

n)=n

−1=o

(n)'>t(n

)=o(

n)'>概率論是乙個很神奇的東西。。。

假設一年有n天,有k個人。

生日相同的兩人對的期望是k(k-1)/(2n), 也就是說o(sqrt(n))的人,生日相同的兩人對的期望數是1; o(sqrt(n))的人至少有一對生日相同的概率大於1/2。(參見算導)

意思就是n個桶,隨機丟sqrt(n)個資料,hash衝突的概率極大!

故一般的hash易被卡。

如果mod 2^64,可人工構造資料卡hash;mod 1e9左右的,可隨機構造資料卡hash。

而雙hash不易被卡。

以下是乙個隨機生成字串的程式。當有兩個長度為l的不同字串hash值相同時輸出並退出。

#define ndebug#include 

#define ll unsigned long long

#define st first

#define nd second

#define pii pair#define pil pair#define pli pair#define pll pair#define pw(x) ((1ll)<

#define lson l, m, rt<<1

#define rson m+1, r, rt<<1|1

using

namespace

std;

/**********

*/template

bool scan (t &ret)

template

inline

int sgn(t a)

template

bool gmax(t1 &a, const t2 &b)

template

bool gmin(t1 &a, const t2 &b)

const

int inf = 0x3f3f3f3f

;const ll inf =1e18;

/**********

*/const ll mod = 1e9+7, base = 997, l = 20, n = 500000

;char s[n+10

];map

string>ma;

void

init()

intmain() );

string

t1, t2;

for(int i = l; i < n; i++) );

else

}cout

<< t1 << endl; cout << t2 <

val = val2 = 0

;

for(int i = 0; i < t1.size(); i++)

return0;

}

view code

2.特徵序列

假設拋一枚標準的硬幣n次,最長連續正面的序列的期望長度有多長?

答案與lgn等階, o(log)。

建堆的複雜度是o(n)

計數排序:先統計一遍字首和,然後逆序插入。

基數排序最好從低有效位開始,從高有效位開始需要分段遞迴。

快排期望複雜度的證明:

經典演算法題集錦

2. 乙個陣列,其中某個數出現的次數超過了一半。求該數。o(n)時間複雜度, o(1)空間複雜度。擴充套件:在乙個陣列中找出出現次數超過n/3的數字。

4 給定乙個未排序陣列。求該陣列在排完序後,連續數字的最大長度。o(nlogn)複雜度,o(n)複雜度。(hashset後,對每個陣列中的數字,找其所在段的最大長度,找的同時刪去找到的數).

5. 完美洗牌演算法。將乙個原始陣列進行置換排序。

6. 二叉排序樹:在一棵排序二叉樹上找與給定值的差值第k小的值。o(nlogn)? o(klogn)? o(k+logn)!

7. 給定乙個長度為n的有序陣列a,找到離目標數m最近的乙個長度為k的區間。 o(k+logn)? o(lognloga)?o(logn+logk)!

8.給定乙個長度為n的無序陣列,任意兩數不同。請找到任意乙個區域性最小值。o(logn)  

演算法導論 趣題集錦(持續更新中)

by 潘雲登 對於商業目的下對本文的任何行為需經作者同意。寫在前面1.本文內容取自 演算法導論 第 2版 題目多為書中習題。書與習題答案可以從這裡 part1 part2 2.所提供的 都是參考書或習題答案編寫,在 gcc 4.3.3 下簡單測試過。3.makefile 檔案可以參考 makefil...

經典排序演算法 集錦

經典排序演算法 這一系列重點在理解,所以例子什麼的都是最簡單的情況,難免失誤之處,多指教 大多數排序演算法都給出了每一步的狀態,以方便初學者更容易理解,通俗易懂,部分難以理解的排序演算法則給出了大量的圖示,也算是乙個特色吧 經典排序演算法 快速排序quick sort 經典排序演算法 桶排序buck...

經典排序演算法集錦

經典排序演算法 這一系列重點在理解,所以例子什麼的都是最簡單的情況,難免失誤之處,多指教 大多數排序演算法都給出了每一步的狀態,以方便初學者更容易理解,通俗易懂,部分難以理解的排序演算法則給出了大量的圖示,也算是乙個特色吧 經典排序演算法 快速排序quick sort 經典排序演算法 桶排序buck...