USING INDUCTION TO DESIGN 使用歸納法設計演算法 [7/14]

來源:互聯網
上載者:User

接上文:http://blog.csdn.net/jj12345jj198999/article/details/6613532

 

名人問題【Q5】【標題3】(不知道業界如何翻譯)

在演算法設計中有一個很流行的練習。這是一個非常好的例子,該例子的解答不需要掃描全部資料(甚至是資料的重要的組成部分)。在n個人中,一個名人被定義為其他人都認識但是自己卻不認識其他人的人。該問題就是存在名人的情況下確定名人,只能通過以一種“您好,請問您認識站在那裡的人嗎?”的方式提問。(假定所有的回答都是正確的,甚至是名人自己也會給出答案)我們的目標是讓最小化提問的次數。由於存在n(n-1)/2對人,在最壞的情況下,如果問題被武斷地提出,有可能需要詢問n(n-1)次問題才行。我們不清楚我們能比最壞的情況做的更好。

在技術上,如果我們建立一個用頂點表示人的有向圖,當A認識B就有一條從A到B的邊,那麼一個名人就對應一個匯點。(非有意的雙關語)也就一個入度為n-1出度為0的頂點。該圖可以用一個n×n鄰接矩陣來表示,如果第i個人認識第j個人那麼在該矩陣中位於第i行第j列的位置被標記為1,否則就為0。該問題也就是通過尋找矩陣中儘可能少的條目確定匯點。

像往常一樣,我們考慮有n-1個人和有n個人時問題的不同之處。既然由定義可知最多存在一個名人,那這裡就有三種可能。其一,名人在前n-1個人中;其二,名人是第n個人;其三,這裡沒有名人。第一種情況最容易處理,我們只需要核對第n個人認識名人,但是名人並不認識第n個人的局面是否存在。其他兩種情況就比較困難了,因為為了確定第n個人是否是名人,我們可能需要提2*(n-1)個問題。在最壞的情況下,這可能會導致n*(n-1)個問題(這是我們試圖避免發生的)。我們需要另一種解法。

這裡的技巧在於從逆向考慮這個問題。確定一個名人可能很難,但是確定某個人不是名人可能要簡單很多。畢竟,很明顯在這裡非名人要比名人多。把某人排除出考慮對把問題規模從n縮減到n-1來說已經足夠了。此外,我們不需要排除出特定的人,任何人都可以。假設我們問Alice她是否認識Bob,如果她認識她就不會是一個名人,如果她不認識
那Bob就不會是一個名人。我們可以通過一個問題排除出他們中間的一個。

現在考慮上面列出的三種情況。我們不只是任意挑選一個人作為第n個人。我們使用上面的思想去排除出Alice和Bob中的一個,然後對其餘包含n-1個人的問題進行求解。我們保證情況2不會發生,因為排除出去的人不可能是名人。此外,如果情況3發生,也就是說在n-1個人中沒有名人,那在n個人中也不會有名人。只有情況1存在,但是正如上面提到的,這種情況很簡單。如果在n-1個人中存在一個名人,只需要提出兩個問題就可以確定整個集合中是否存在名人了。否則就不會有名人存在。

所得到的演算法如下。我們問A是否認識B,根據A的回答排除掉他們其中的一個。假設排除的是A,然後我們在剩下的n-1個人中尋找(通過歸納法)一個名人。如果沒有名人,那麼演算法就終止。否則我們核實A認識名人但是名人不認識A這種局面。下面給出一個非遞迴的演算法實現。

名人演算法(已知n×n的布爾矩陣)
begin
   i:=1;
   j:=2;
   next:=2;
   {在第一步中我們排除了除了一個候選人以外的所有人}
   while next≤n do
      next:=next+1;
   if Know[i,j] then i:=next;
      else j:=next;
   {我們排除i和j中的一個} 
   if i=n+1 then candidate:=j else candidate:=i;
   {現在我們核實該候選人是否確實是名人}
   wrong:=false;k:=1;
   Know[candidate,candidate]:=false;
     {只是一個用來測試的虛擬變數}
   while not wrong and k≤n do
      if Know[candidate,k] then wrong:=true;
   if not Know[k,candidate] then
      if candidate ≠ k then wrong:=true;
   k:=k+1;
   if not wrong then print"candidate is a celebrity!"
end;

複雜度:這裡最多隻需要提3*(n-1)個問題。在第一步中提n-1個問題從而從候選人中排除掉n-1個人。為了確定那個候選人是否是名人最多隻需要提2*(n-1)個問題。上面給出的解答表明可以在鄰接矩陣中僅尋找O(n)條記錄就能確定一個名人,儘管從推理上認為問題的解法與n(n-1)項輸入都密切相關。(這裡也可能節省掉額外的log2(n)【取下限】次提問,只需要在驗證過程中以及提問排除過程中注意避免重複即可)

總結:這個極佳的解法的核心思想在於用一種明智的方式把問題規模從n縮減到n-1。這個例子表明了有時候在更有效進行問題規模的縮減上花一些努力(在該例子中提出一個疑問)是值得的。此外,逆向思維在本問題中顯得很有用。與其去尋找一個名人我們不如嘗試去排除非名人。這在數學證明時經常用到。一個人不需要直接去嘗試解決問題。有時解決能夠給原先問題帶來解答的相關問題要簡單一些。為了找到這些相關的問題,在開始時使用成品(數學證明中的得到的定理),然後逆向進行我們的工作看看實現這個成品需要什麼東西,這往往是很有用的做法。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.