1. 程式人生 > >有難度的演算法筆試題:晶片測試

有難度的演算法筆試題:晶片測試

有難度的演算法筆試題

摘自:http://community.csdn.net/Expert/TopicView3.asp?id=5764920

3)晶片測試:

有2k塊晶片,已知好晶片比壞晶片多。請設計演算法從其中找出一片好晶片,說明你所用的比較次數上限。
其中:
好晶片和其它晶片比較時,能正確給出另一塊晶片是好還是壞。
壞晶片和其它晶片比較時,會隨機的給出好或是壞。 

試著回答一下第三題,不保證最快效率:
1.對N個晶片,在保證好晶片比壞晶片多的情況下,取出一塊晶片(為敘述方便,設為晶片X),與其他所有晶片做測試,記錄相互間的結果.
2.按照晶片X對其他晶片的結果,將其他晶片分成兩組:GOOD組和BAD組.
3.如果GOOD組的數目<BAD的數目,則X為壞晶片,跳到5.
4. 如果GOOD組的數目>=BAD組的數目,並且GOOD組對X的測試為good(認為X好晶片),則X確實是好晶片,演算法結束(因為在N-1中,至 少半數的晶片認為X為不是壞晶片,考慮到"好晶片比壞晶片多",可歸謬證明);否則,只要有一個GOOD組晶片對X的測試為bad,則X為壞晶片,繼續.
5.X為壞晶片,故去除X,將所有晶片分成兩組:對X的測試為bad的保留,對X的測試為good的去除.考慮到所有的好晶片都保留了(它們對X的測試必為bad),所以仍然滿足"好晶片比壞晶片多"的條件.跳到1,繼續.

以上演算法保證可以結束.因為如果測試出X是壞的,那麼每次N至少減一.並且,因為"好晶片比壞晶片多",演算法必定是在第4步結束.而不會出現晶片降到1的情況(只要初始的晶片數>=2)

題目中,初始N=2k.其複雜度在最壞的情況下測試次數(假設一次測試同時出現相互的結果,否則次數*2)為: k + (k+1) + ... + (2k-1) = 1/2 * k(3k-1) = O(k^2)


下面兩個結論比較有用,先列出來。

任意拿兩片晶片互相測試,則有
1)結果都為真,則說明兩片都為真,或者都為假。
2)其他結果,則最少有一為假。

在任意偶數多的晶片裡,如果好晶片多於壞晶片,將所有晶片兩兩分組,根據抽屜原理,則有
1)必有兩個好晶片分在一組。
2)同為好晶片的組數一定多於同為壞晶片的組數。

測試流程
1)將晶片兩兩分組,比如1和2,3和4。。。。2k-1和2k。互相測試,則必有結果同為真的組。
2)保留結果同為真的組,丟棄其他組。必有好晶片組多於壞晶片組。(所以當只有兩組或者一組同為真時,則必為真,測試結束)
3)結果同為真的組晶片必定同好或者同壞,所以可以丟棄一半。從所有同真組中任意取出一個丟棄另一個,組成新的測試組,繼續兩兩分組,直到同真組只有2個或者1個測試結束,堅持到最後的就是好晶片。

說 明:同真組可能會變成奇數個,當為奇陣列時,任意選一組取其中一個(假設為A),在剩餘組中各取一個來測試A,如果測試結果A為好晶片過半或者等於一半, 則A為好晶片,測試結束。否則A為壞晶片,判定A為好晶片的必為壞晶片,剔除後剩餘部分形成新的測試組,繼續兩兩分組。。。

總的原理和淘 金差不多,剛開始好的晶片多,在每次剔除晶片時一定要保證剔除的壞晶片數量一定要多於或者等於好晶片的數量,這樣就能保證在剩餘的晶片中好的一定多於壞 的。當組數為奇數時採用投票制,多於半數的投票有效(等於也有效,因為好的多於壞的,相等則被測試的一定為好的)。

因為每次最少剔除一半的晶片,所以最壞情況出現在每次只能剔除一半晶片的時候,按等比數列遞減。當有N個晶片時,測試次數為n+(n/2)+(n/4)...=2n(實際上當為奇陣列時,次數會更多,不過算不過來了,省略^_^ )


xlfddlfd 的演算法很好,學習一下.

這個演算法比我之前的演算法要快得多.
當最壞情況是,每次都是奇數,並且每次都是壞晶片 時,測試次數(lg是以2為底的對數,N = 2k)約為 2(k + k/2 + k/4+...)-slgk = 4k - slgk = O(k),仍然是線性演算法(此處的s為不大的常數(但大於1),因為在每次為奇數的情況下,實際的數目要比 k/2, k/4 之類的小,可以認為這個誤差是lgk的倍數,此外壞晶片的比較數是每次總個數-1,所以要減少大約一個lgk).