程序員有趣的面試智力題


偶然間在網上看到幾個原來沒見過的面試智力題,有幾個題目在國內流傳相當廣,什麼n個人怎麼分餅最公平,屋裏的三個燈泡分別由哪個開關控制,三架飛機環遊世界,用火柴和兩根繩子測量45分鐘之類的題目,火星得已經可以考古了,這裏就不再說了。

     1、考慮一個雙人遊戲。遊戲在一個圓桌上進行。每個遊戲者都有足夠多的硬幣。他們需要在桌子上輪流放置硬幣,每次必需且只能放置一枚硬幣,要求硬幣完全置於桌面內(不能有一部分懸在桌子外面),並且不能與原來放過的硬幣重疊。誰沒有地方放置新的硬幣,誰就輸了。遊戲的先行者還是後行者有必勝策略?這種策略是什麼?
    答案:先行者在桌子中心放置一枚硬幣,以後的硬幣總是放在與後行者剛纔放的地方相對稱的位置。這樣,只要後行者能放,先行者一定也有地方放。先行者必勝。

    2、 用線性時間和常數附加空間將一篇文章的單詞(不是字符)倒序。
    答案:先將整篇文章的所有字符逆序(從兩頭起不斷交換位置相對稱的字符);然後用同樣的辦法將每個單詞內部的字符逆序。這樣,整篇文章的單詞順序顛倒了,但單詞本身又被轉回來了。

    3、 用線性時間和常數附加空間將一個長度爲n的字符串向左循環移動m位(例如,"abcdefg"移動3位就變成了"defgabc")。
    答案:把字符串切成長爲m和n-m的兩半。將這兩個部分分別逆序,再對整個字符串逆序。

    4、一個矩形蛋糕,蛋糕內部有一塊矩形的空洞。只用一刀,如何將蛋糕切成大小相等的兩塊?
    答案:注意到平分矩形面積的線都經過矩形的中心。過大矩形和空心矩形各自的中心畫一條線,這條線顯然把兩個矩形都分成了一半,它們的差當然也是相等的。

    5、 一塊矩形的巧克力,初始時由N x M個小塊組成。每一次你只能把一塊巧克力掰成兩個小矩形。最少需要幾次才能把它們掰成N x M塊1x1的小巧克力?
    答案:N x M - 1次顯然足夠了。這個數目也是必需的,因爲每掰一次後當前巧克力的塊數只能增加一,把巧克力分成N x M塊當然需要至少掰N x M - 1次。

    6、如何快速找出一個32位整數的二進制表達裏有多少個"1"?用關於"1"的個數的線性時間?
    答案1(關於數字位數線性):for(n=0; b; b >>= 1) if (b & 1) n++;
    答案2(關於"1"的個數線性):for(n=0; b; n++) b &= b-1;

    7、 一個大小爲N的數組,所有數都是不超過N-1的正整數。用O(N)的時間找出重複的那個數(假設只有一個)。一個大小爲N的數組,所有數都是不超過N+1的正整數。用O(N)的時間找出沒有出現過的那個數(假設只有一個)。
    答案:計算數組中的所有數的和,再計算出從1到N-1的所有數的和,兩者之差即爲重複的那個數。計算數組中的所有數的和,再計算出從1到N+1的所有數的和,兩者之差即爲缺少的那個數。

    8、 給出一行C語言表達式,判斷給定的整數是否是一個2的冪。
    答案:(b & (b-1)) == 0

    9、地球上有多少個點,使得從該點出發向南走一英里,向東走一英里,再向北走一英里之後恰好回到了起點?
    答案:“北極點”是一個傳統的答案,其實這個問題還有其它的答案。事實上,滿足要求的點有無窮多個。所有距離南極點1 + 1/(2π)英里的地方都是滿足要求的,向南走一英里後到達距離南極點1/(2π)的地方,向東走一英里後正好繞行緯度圈一週,再向北走原路返回到起點。事實上,這仍然不是滿足要求的全部點。距離南極點1 + 1/(2kπ)的地方都是可以的,其中k可以是任意一個正整數。

      10、A、B兩人分別在兩座島上。B生病了,A有B所需要的藥。C有一艘小船和一個可以上鎖的箱子。C願意在A和B之間運東西,但東西只能放在箱子裏。只要箱子沒被上鎖,C都會偷走箱子裏的東西,不管箱子裏有什麼。如果A和B各自有一把鎖和只能開自己那把鎖的鑰匙,A應該如何把東西安全遞交給B?
    答案:A把藥放進箱子,用自己的鎖把箱子鎖上。B拿到箱子後,再在箱子上加一把自己的鎖。箱子運回A後,A取下自己的鎖。箱子再運到B手中時,B取下自己的鎖,獲得藥物。

    11、 一對夫婦邀請N-1對夫婦參加聚會(因此聚會上總共有2N人)。每個人都和所有自己不認識的人握了一次手。然後,男主人問其餘所有人(共2N-1個人)各自都握了幾次手,得到的答案全部都不一樣。假設每個人都認識自己的配偶,那麼女主人握了幾次手?
    答案:握手次數只可能是從0到2N-2這2N-1個數。除去男主人外,一共有2N-1個人,因此每個數恰好出現了一次。其中有一個人(0)沒有握手,有一個人(2N-2)和所有其它的夫婦都握了手。這兩個人肯定是一對夫妻,否則後者將和前者握手(從而前者的握手次數不再是0)。除去這對夫妻外,有一個人(1)只與(2N-2)握過手,有一個人(2N-3)和除了(0)以外的其它夫婦都握了手。這兩個人肯定是一對夫妻,否則後者將和前者握手(從而前者的握手次數不再是1)。以此類推,直到握過N-2次手的人和握過N次手的人配成一對。此時,除了男主人及其配偶以外,其餘所有人都已經配對。根據排除法,最後剩下來的那個握手次數爲N-1的人就是女主人了。

 

    12、兩個機器人,初始時位於數軸上的不同位置。給這兩個機器人輸入一段相同的程序,使得這兩個機器人保證可以相遇。程序只能包含“左移n個單位”、“右移n個單位”,條件判斷語句If,循環語句while,以及兩個返回Boolean值的函數“在自己的起點處”和“在對方的起點處”。你不能使用其它的變量和計數器。
    答案:兩個機器人同時開始以單位速度右移,直到一個機器人走到另外一個機器人的起點處。然後,該機器人以雙倍速度追趕對方。程序如下。

while(!at_other_robots_start) {
  move_right 1
}
while(true) {
  move_right 2
}

    13、 如果叫你從下面兩種遊戲中選擇一種,你選擇哪一種?爲什麼?
      a. 寫下一句話。如果這句話爲真,你將獲得10美元;如果這句話爲假,你獲得的金錢將少於10美元或多於10美元(但不能恰好爲10美元)。
      b. 寫下一句話。不管這句話的真假,你都會得到多於10美元的錢。
    答案:選擇第一種遊戲,並寫下“我既不會得到10美元,也不會得到10000000美元”。


      14、你在一幢100層大樓下,有21根電線線頭標有數字1..21。這些電線一直延伸到大樓樓頂,樓頂的線頭處標有字母A..U。你不知道下面的數字和上面的字母的對應關係。你有一個電池,一個燈泡,和許多很短的電線。如何只上下樓一次就能確定電線線頭的對應關係?
       答案:在下面把2,3連在一起,把4到6全連在一起,把7到10全連在一起,等等,這樣你就把電線分成了6個“等價類”,大小分別爲1, 2, 3, 4, 5, 6。然後到樓頂,測出哪根線和其它所有電線都不相連,哪些線和另外一根相連,哪些線和另外兩根相連,等等,從而確定出字母A..U各屬於哪個等價類。現在,把每個等價類中的第一個字母連在一起,形成一個大小爲6的新等價類;再把後5個等價類中的第二個字母連在一起,形成一個大小爲5的新等價類;以此類推。回到樓下,把新的等價類區別出來。這樣,你就知道了每個數字對應了哪一個原等價類的第幾個字母,從而解決問題。

    15、某種藥方要求非常嚴格,你每天需要同時服用A、B兩種藥片各一顆,不能多也不能少。這種藥非常貴,你不希望有任何一點的浪費。一天,你打開裝藥片A的藥瓶,倒出一粒藥片放在手心;然後打開另一個藥瓶,但不小心倒出了兩粒藥片。現在,你手心上有一顆藥片A,兩顆藥片B,並且你無法區別哪個是A,哪個是B。你如何才能嚴格遵循藥方服用藥片,並且不能有任何的浪費?
    答案:把手上的三片藥各自切成兩半,分成兩堆擺放。再取出一粒藥片A,也把它切成兩半,然後在每一堆里加上半片的A。現在,每一堆藥片恰好包含兩個半片的A和兩個半片的B。一天服用其中一堆即可。

     16、 你在一個飛船上,飛船上的計算機有n個處理器。突然,飛船受到外星激光武器的攻擊,一些處理器被損壞了。你知道有超過一半的處理器仍然是好的。你可以向一個處理器詢問另一個處理器是好的還是壞的。一個好的處理器總是說真話,一個壞的處理器總是說假話。用n-2次詢問找出一個好的處理器。
       答案:給處理器從1到n標號。用符號a->b表示向標號爲a的處理器詢問處理器b是不是好的。首先問1->2,如果1說不是,就把他們倆都去掉(去掉了一個好的和一個壞的,則剩下的處理器中好的仍然過半),然後從3->4開始繼續發問。如果1說2是好的,就繼續問2->3,3->4,……直到某一次j說j+1是壞的,把j和j+1去掉,然後問j-1 -> j+2;或者從j+2 -> j+3開始發問,如果前面已經沒有j-1了(之前已經被去掉過了)。注意到你始終維護着這樣一個“鏈”,前面的每一個處理器都說後面那個是好的。這條鏈裏的所有處理器要麼都是好的,要麼都是壞的。當這條鏈越來越長,剩下的處理器越來越少時,總有一個時候這條鏈超過了剩下的處理器的一半,此時可以肯定這條鏈裏的所有處理器都是好的。或者,越來越多的處理器都被去掉了,鏈的長度依舊爲0,而最後只剩下一個或兩個處理器沒被問過,那他們一定就是好的了。另外注意到,第一個處理器的好壞從來沒被問過,仔細想想你會發現最後一個處理器的好壞也不可能被問到(一旦鏈長超過剩餘處理器的一半,或者最後沒被去掉的就只剩這一個了時,你就不問了),因此詢問次數不會超過n-2。

      17、一個圓盤被塗上了黑白二色,兩種顏色各佔一個半圓。圓盤以一個未知的速度、按一個未知的方向旋轉。你有一種特殊的相機可以讓你即時觀察到圓上的一個點的顏色。你需要多少個相機才能確定圓盤旋轉的方向?
      答案:你可以把兩個相機放在圓盤上相近的兩點,然後觀察哪個點先變色。事實上,只需要一個相機就夠了。控制相機繞圓盤中心順時針移動,觀察顏色多久變一次;然後讓相機以相同的速度逆時針繞着圓盤中心移動,再次觀察變色的頻率。可以斷定,變色頻率較慢的那一次,相機的轉動方向是和圓盤相同的。

     18、有25匹馬,速度都不同,但每匹馬的速度都是定值。現在只有5條賽道,無法計時,即每賽一場最多隻能知道5匹馬的相對快慢。問最少賽幾場可以找出25匹馬中速度最快的前3名?百度2008年面試題

每匹馬都至少要有一次參賽的機會,所以25匹馬分成5組,一開始的這5場比賽是免不了的。接下來要找冠軍也很容易,每一組的冠軍在一起賽一場就行了(第6場)。最後就是要找第2和第3名。我們按照第6場比賽中得到的名次依次把它們在前5場比賽中所在的組命名爲A、B、C、D、E。即:A組的冠軍是第6場的第1名,B組的冠軍是第6場的第2名……每一組的5匹馬按照他們已經賽出的成績從快到慢編號:

A組:1,2,3,4,5
B組:1,2,3,4,5
C組:12,3,4,5
D組:1,2,3,4,5
E組:1,2,3,4,5

從現在所得到的信息,我們可以知道哪些馬已經被排除在3名以外。只要已經能確定有3匹或3匹以上的馬比這匹馬快,那麼它就已經被淘汰了。可以看到,只有上表中粗體藍色的那5匹馬纔有可能爲2、3名的。即:A組的2、3名;B組的1、2名,C組的第1名。取這5匹馬進行第7場比賽,第7場比賽的前兩名就是25匹馬中的2、3名。故一共最少要賽7場。

這道題有一些變體,比如64匹馬找前4名。方法是一樣的,在得出第1名以後尋找後3名的候選競爭者就可以了。

      19、IBM筆試題:一普查員問一女人,“你有多少個孩子,他們多少歲?”
女人回答:“我有三個孩子,他們的歲數相乘是36,歲數相加就等於旁邊屋的門牌號碼。“普查員立刻走到旁邊屋,看了一看,回來說:“我還需要多少資料。”女人回答:“我現在很忙,我最大的孩子正在樓上睡覺。”普查員說:”謝謝,我己知道了。”
問題:那三個孩子的歲數是多少。
36 = 1 × 2 × 2 × 3 × 3
所有的可能爲
1,1,36;sum = 38
1,2,18;sum = 21
1,3,12;sum = 16
1,4,9;sum = 14
1,6,6;sum = 13
2,2,9;sum = 13
2,3,6;sum = 11
3,3,4;sum = 10
由於普查員知道了年齡和之後還是不能確定每個孩子的年齡,所以可能性爲
1,6,6;sum = 13
2,2,9;sum = 13
由於最大(暗含只有一個最大)的孩子在睡覺,所以只可能是
2,2,9;sum = 13

      20、有7克、2克砝碼各一個,天平一隻,如何只用這些物品三次將140克的鹽分成50、90克各一份?
答:第一步:把140克鹽分成兩等份,每份70克。
第二步:把天平一邊放上2+7克砝碼,另一邊放鹽,這樣就得到9克和61克分開的鹽。
第三步:將9克鹽和2克砝碼放在天平一邊,另一邊放鹽,這樣就得到11克和50克。於是50和90就分開了。

     21、有三筐水果,一筐裝的全是蘋果,第二筐裝的全是橘子,第三筐是橘子與蘋果混在一起。筐上的標籤都是騙人的,(比如,如果標籤寫的是橘子,那麼可以肯定筐裏不會只有橘子,可能還有蘋果)你的任務是拿出其中一筐,從裏面只拿一隻水果,然後正確寫出三筐水果的標籤。
答:從貼有蘋果和橘子標籤的筐中拿出一個水果,如果是蘋果,說明這個筐中全是蘋果,那麼貼蘋果標籤的筐裏裝的全是桔子,則貼有桔子標籤的筐中裝的蘋果和桔子;如果拿出的一個水果是桔子,說明這個筐中全是桔子,那麼貼桔子標籤的筐裏裝的全是蘋果,貼蘋果標籤的筐裏裝的是蘋果和桔子。

      22、題目如下:
  0 1 2 3 4 5 6 7 8 9
  _ _ _ _ _ _ _ _ _ _

在橫線上填寫數字,使之符合要求。
要求如下:對應的數字下填入的數,代表上面的數在下面出現的次數,比如3下面是1,代表3要在下面出現一次。

正確答案是:0 1 2 3 4 5 6 7 8 9
                       6 2 1 0 0 0 1 0 0 0

我的思路是:因爲第二行的數字是第一行的數在下面出現的次數,下面10個格子,總共10次。。。所以第2排數字之和爲10。

首先從0入手,先填9,肯定不可能,9下面要是1,只剩8個位填0,不夠填8,8下面要填1,1要至少填2,後面不用再想,因爲已經剩下7個位置,不夠填0……如此類推。到0下面填6的時候就得到我上面的答案了。。

其實可以推出這個題目的兩個關鍵條件:
1、第2排數字之和爲10。
2、兩排數字上下相乘之和也是10!
滿足這兩個條件的就是答案,下面來編寫程序實現!

  1. //原始數值: 0,1,2,3,4,5,6,7,8,9  
  2. //出現次數: 6,2,1,0,0,0,1,0,0,0  
  3. #include "iostream"  
  4. using namespace std;  
  5. #define len 10  
  6. class NumberTB  
  7. {  
  8. private:  
  9.     int top[len];  
  10.     int bottom[len];  
  11.     bool success;  
  12. public:  
  13.     NumberTB();  
  14.     int *getBottom();  
  15.     void setNextBottom();  
  16.     int getFrequecy(int num);  
  17. };  
  18. NumberTB::NumberTB()  
  19. {  
  20.     success = false;  
  21.     //format top  
  22.     for(int i = 0; i < len; i++)  
  23.     {  
  24.         top[i] = i;  
  25.     }  
  26. }  
  27. int *NumberTB::getBottom()  
  28. {  
  29.     int i = 0;  
  30.     while(!success)  
  31.     {  
  32.         i++;  
  33.         setNextBottom();  
  34.     }  
  35.     return bottom;  
  36. }  
  37. //set next bottom  
  38. void NumberTB::setNextBottom()  
  39. {  
  40.     bool reB = true;  
  41.     for(int i = 0; i < len; i++)  
  42.     {  
  43.         int frequecy = getFrequecy(i);  
  44.         if(bottom[i] != frequecy)  
  45.         {  
  46.             bottom[i] = frequecy;  
  47.             reB = false;  
  48.         }  
  49.     }  
  50.     success = reB;  
  51. }  
  52. //get frequency in bottom  
  53. int NumberTB::getFrequecy(int num) //此處的num 即指上排的數i  
  54. {  
  55.     int count = 0;  
  56.     for(int i = 0; i < len; i++)  
  57.     {  
  58.         if(bottom[i] == num)  
  59.             count++;  
  60.     }  
  61.     return count; //cout 即對應frequecy  
  62. }  
  63. int main(void)  
  64. {  
  65.     int i;  
  66.     NumberTB nTB;  
  67.     int *result = nTB.getBottom();  
  68.     cout<<"原始數值:";  
  69.     for(i=0;i<10;i++)  
  70.         cout<<i<<"  ";  
  71.     cout<<endl;  
  72.     cout<<"出現次數:";  
  73.     for(i = 0; i < len; i++)  
  74.     {  
  75.         cout << *result++ <<"  ";  
  76.     }  
  77.     cout<<endl;  
  78.     system("pause");  
  79.     return 0;  
  80. }  

轉自:http://blog.csdn.net/hackbuteer1/article/details/6726419

發佈了18 篇原創文章 · 獲贊 13 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章