《微軟等數據結構+算法面試100題》自娛自解(完結)ZHUAN

http://m.blog.csdn.net/blog/lzc52151/6221852

2011-3-3閱讀2400 評論4


這段日子工作不忙,心情也不錯,爲了娛樂和乾點什麼,把網上的一篇貼《微軟等數據結構+算法面試100題》做了一遍。感覺不錯,大部分是比較基礎。除了個別語法題由於對該語言不熟無法下手之外,其餘的連查帶想地全部搞定!邊做的同時也做了些記錄工作,大都是寫出了思路或算法。覺得個別有必要編碼驗證的也實驗了,當然,有一部分是編碼驗證計劃中的,回來有時間慢慢完成。

此刻,想起前輩的那句話:先了解一些XXX、掌握XXX等知識,一般的題就不在話下了。

什麼叫一般的題?這些算嗎?雖然略有些小成就感,但自知對某些知識掌握還是不透。有時瞪大了雙眼也看不出問題所在,有種文盲看報的感覺,自知水平還是有待提高的。

不管如何,路還很長,慢慢走吧。這也算一個小測驗吧,在此處留個存照。

爲了尊重版權,這是原貼地址:http://blog.csdn.net/v_JULY_v/archive/2010/12/06/6057286.aspx

下面是我的記錄,黑字是原題,藍色部分是我敲的。

===============================================

《微軟等數據結構+算法面試100題》自娛自解(完結)

1.把二元查找樹轉變成排序的雙向鏈表
 
題目:
輸入一棵二元查找樹,將該二元查找樹轉換成一個排序的雙向鏈表。
要求不能創建任何新的結點,只調整指針的指向。
   10
  / /
  6  14
 / / / /
4  8 12 16
 轉換成雙向鏈表
4=6=8=10=12=14=16。
 
 首先我們定義的二元查找樹 節點的數據結構如下:
 struct BSTreeNode
{
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
};

 中序遍歷
2.
設計包含min函數的棧。
定義棧的數據結構,要求添加一個min函數,能夠得到棧的最小元素。
要求函數min、push以及pop的時間複雜度都是O(1)。

 棧上加鍊形堆
3.
求子數組的最大和
題目:
輸入一個整形數組,數組裏有正數也有負數。
數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。
求所有子數組的和的最大值。要求時間複雜度爲O(n)。

例如輸入的數組爲1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組爲3, 10,-4, 7, 2,
因此輸出爲該子數組的和18。

 動態規劃,end[i]表示以i結尾的和最大子數組,end[i]=max{end[i-1]+a[i],a[i]}

4.在二元樹中找出和爲某一值的所有路徑

題目:輸入一個整數和一棵二元樹。
從樹的根結點開始往下訪問一直到葉結點所經過的所有結點形成一條路徑。
打印出和與輸入整數相等的所有路徑。
例如 輸入整數22和如下二元樹
  10  
  / /   
 5  12   
 /   /   
4     7
則打印出兩條路徑:10, 12和10, 5, 7。

二元樹節點的數據結構定義爲:
struct BinaryTreeNode // a node in the binary tree
{
int m_nValue; // value of node
BinaryTreeNode *m_pLeft; // left child of node
BinaryTreeNode *m_pRight; // right child of node
};

 前序遍歷樹。每遇到一個新節點,把值與父節點的值加起來。到葉子時,加完後葉子上的值如果等於給出數,則認爲存在一條可用路徑。

5.查找最小的k個元素
題目:輸入n個整數,輸出其中最小的k個。
例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字爲1,2,3和4。

 建個大小爲K的大根堆
第6
騰訊面試題: 
給你10分鐘時間,根據上排給出十個數,在其下排填出對應的十個數 
要求下排每個數都是先前上排那十個數在下排出現的次數。 
上排的十個數如下: 
【0,1,2,3,4,5,6,7,8,9】

舉一個例子, 
數值: 0,1,2,3,4,5,6,7,8,9 
分配: 6,2,1,0,0,0,1,0,0,0 
0在下排出現了6次,1在下排出現了2次, 
2在下排出現了1次,3在下排出現了0次.... 
以此類推..

十個數n=10,下排表示數字個數,因此下排的和必定爲10。而全爲1的情況是不成立的,那麼也就是說最少有一個大於1或者說至少有一個0存在。設下排0下的數字是x(x>0),表示下排有x個0。

那麼1~9中必定有x個0,下排1~9的數字和爲10-x,而又有x個0存在,那麼不是0的位置有9-x個。那麼,把10-x個數放到9-x位置上,應該有1個2,8-x個1,而0對應的下排數x應該也對應其中一個1有:

0 1  2…x…

x 8-x 1…1…

如果8-x=2,則x=6恰好有:

0 1 2 3 4 5 6 7 8 9

6 2 1 0 0 0 1 0 0 0

一般地,n>6的時候都可以用這種方法求得。小於6的情況還沒想到通用的方法。。。
第7
微軟亞院之編程判斷倆個鏈表是否相交
給出倆個單向鏈表的頭指針,比如h1,h2,判斷這倆個鏈表是否相交。
爲了簡化問題,我們假設倆個鏈表均不帶環。

分別遍歷兩個鏈表,遍歷到尾時,最後一個元素地址相同則相交。

問題擴展:
1.
如果鏈表可能有環列?

兩個鏈表任取一個鏈表頭開始遍歷,每遍歷一個元素都與兩個表頭指針對比。如果能遍歷到尾則不存在環,解答如上。如果碰到指針等於自己的表頭,則放棄此鏈表遍歷,開始遍歷另一個鏈表。如果遇到另一個表頭,則兩鏈表相交。發生其他情況(兩表都到自己表頭,一表到尾一表回到自己表頭,兩表到不同的尾),則不相交。
2.
如果需要求出倆個鏈表相交的第一個節點列?

 如果不帶環,則分別遍歷兩表,記錄各自長度x、y,說明其中一表比另一表長x-y,讓其先走x-y步。再兩表同步前進至兩指針相同,則爲交點。

如果帶環,分別遍歷。如果一表遇到另一表頭,記錄長度x,開始遍歷另一表,至自己表頭記y,再讓記錄長度爲x的表從頭開始先走x-y步,再兩表同步前進至兩指針相同,則爲交點。如果先遍歷到自己則記y,開始遍歷另一表,至同一位置記x,再讓記錄長度爲x的表從頭開始先走x-y步,再兩表同步前進至兩指針相同,則爲交點。

第8
此貼選一些 比較怪的題,,由於其中題目本身與算法關係不大,僅考考思維。特此並作一題。
1.有兩個房間,一間房裏有三盞燈,另一間房有控制着三盞燈的三個開關,

這兩個房間是 分割開的,從一間裏不能看到另一間的情況。
現在要求受訓者分別進這兩房間一次,然後判斷出這三盞燈分別是由哪個開關控制的。
有什麼辦法呢?

開一盞燈,過十分鐘再開一盞,此時進去,可辨別未開的燈對應未按的開關,用手摸摸,熱的對應第一個開關

2.你讓一些人爲你工作了七天,你要用一根金條作爲報酬。金條被分成七小塊,每天給出一塊。
如果你只能將金條切割兩次,你怎樣分給這些工人?

切成124。第一天給一塊,第二天,用二換一,第三天給一,第四天用三換四,第五天給一,第六天用二換一,第七天給一。

<!--[if !supportLists]-->3.      <!--[endif]-->★用一種算法來顛倒一個鏈接表的順序。現在在不用遞歸式的情況下做一遍。

聲明三個指針分別指向當前節點,下一節點,下下節點。不遞歸就用循環。
  ★用一種算法在一個循環的鏈接表裏插入一個節點,但不得穿越鏈接表。

什麼叫穿越鏈接表?用最普通的指針重定向不行麼?
  ★用一種算法整理一個數組。你爲什麼選擇這種方法?

要整理成什麼樣?排序的話,那就得看數組的狀況,選擇合適的排序算法。
  ★用一種算法使通用字符串相匹配。

只實現點和星?從頭至尾匹配就行。遇到點就跳過該字符,遇到星就尋找星後面的字符,然後從星後面的字符重新開始匹配。
  ★顛倒一個字符串。優化速度。優化空間。

首尾交換並向中間推進,直到尾指針不大於首指針。時間O(n/2),空間爲O(1)。
  ★顛倒一個句子中的詞的順序,比如將“我叫克麗絲”轉換爲“克麗絲叫我”,

實現速度最快,移動最少。

怎麼樣的移動最少,是打印出來,還是賦給原字符串?打印出來的話,字符串完全可以移動量爲0。賦給原字符串,首地址能變不,不能變那移動量可能會達到n。首地址可變的話,把謂語和主語放在賓語後面,首地址指向賓語就可以。
  ★找到一個子字符串。優化速度。優化空間。

KMP算法。
  ★比較兩個字符串,用O(n)時間和恆量空間。

每次取一個字符相比,直至取到的兩個字符不同停止。
  ★假設你有一個用1001個整數組成的數組,這些整數是任意排列的,但是你知道所有的整數都在1到1000(包括1000)之間。此外,除一個數字出現兩次外,其他所有數字只出現一次。假設你只能對這個數組做一次處理,用一種算法找出重複的那個數字。如果你在運算中使用了輔助的存儲方式,那麼你能找到不用這種方式的算法嗎?

取第一個數,如果是6,把它與第6位交換,再看原來第6位(放手裏)數字,如果是9,把原來第6位數字與第9位交換,再看原來第9位數字(放手裏)……直到某位上已經放了某個數,而手裏的數與之相同,則該數爲所求。

  ★不用乘法或加法增加8倍。現在用同樣的方法增加7倍。

 左移三位即乘8,左移三位乘8再減去原數即是7倍


第9
判斷整數序列是不是二元查找樹的後序遍歷結果
題目:輸入一個整數數組,判斷該數組是不是某二元查找樹的後序遍歷的結果。
如果是返回true,否則返回false。

例如輸入5、7、6、9、11、10、8,由於這一整數序列是如下樹的後序遍歷結果:

         8
      /  /
     6    10
    / /  / /
   5  7 9  11
因此返回true
如果輸入7、4、6、5,沒有哪棵樹的後序遍歷的結果是這個序列,因此返回false。

 分治。從給定串最後一個數開始,如果它前面的數能分爲連續的兩段,一段比它大,一段比這,則以此數爲根的樹該層上後序存在。再分別對分成的前後兩段分別重複上面的操作,如果所有點都可以如此分割,則認爲該序列是一個後序遍歷序列,否則不是。

第10
翻轉句子中單詞的順序。
題目:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。

句子中單詞以空格符隔開。爲簡單起見,標點符號和普通字母一樣處理。
例如輸入“I am a student.”,則輸出“student.a am I”。

 開闢一塊新空間,原字符串從後往前遍歷,遇到空格就往新空間裏寫,直至原符串遍歷完畢。

第11題

求二叉樹中節點的最大距離...

如果我們把二叉樹看成一個圖,父子節點之間的連線看成是雙向的,
我們姑且定義"距離"爲兩節點之間邊的個數。
寫一個程序,
求一棵二叉樹中相距最遠的兩個節點之間的距離。

 動態規劃

maxlength(i)=max{ maxlength (i->left), maxlength(i->right),high(i->left)+high(i->right)+1}

第12
題目:求1+2+…+n,
要求不能使用乘除法、for、while、if、else、switch、case等關鍵字以及條件判斷語句(A?B:C)。

 這題還沒有想到好的解法,不知道原題是想用什麼語言。C++、JAVA可以用模板來實現。至於C,只想到嵌彙編來做。

第13題:
題目:輸入一個單向鏈表,輸出該鏈表中倒數第k個結點。鏈表的倒數第0個結點爲鏈表的尾指針。
鏈表結點定義如下:  
struct ListNode
{
  int m_nKey;
  ListNode* m_pNext;
};

 某個指針先走K-1步,再加一個指針從頭開始,兩個指針同步進行,當前一個指針到尾,後一指針指向倒數第K個節點。

第14題:
題目:輸入一個已經按升序排序過的數組和一個數字,
在數組中查找兩個數,使得它們的和正好是輸入的那個數字。
要求時間複雜度是O(n)。如果有多對數字的和等於輸入的數字,輸出任意一對即可。
例如輸入數組1、2、4、7、11、15和數字15。由於4+11=15,因此輸出4和11。

 兩頭夾啊,兩頭分別設一個指針,兩數相加,大於15則,右邊指針的下標減一,小於15則左邊指針的下標加一,直至兩數相加爲15。

第15題:
題目:輸入一顆二元查找樹,將該樹轉換爲它的鏡像,
即在轉換後的二元查找樹中,左子樹的結點都大於右子樹的結點。
用遞歸和循環兩種方法完成樹的鏡像轉換。  
例如輸入:
  8
  / /
  6 10
 // //
5 7 9 11

輸出:
   8
  / /
 10 6
 // //
11 9 7 5

定義二元查找樹的結點爲:
struct BSTreeNode // a node in the binary search tree (BST)
{
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
};

 遞歸時先求遞歸調用子問題,再換左右指針,即類似後序遍歷。用循環時好像用層次遍歷和後序遍歷都可以。

第16題:
題目(微軟):
輸入一顆二元樹,從上往下按層打印樹的每個結點,同一層中按照從左往右的順序打印。  
例如輸入

   8
  / /
 6 10
/ / / /
5 7 9 11

輸出8 6 10 5 7 9 11

 樹的層次遍歷,或叫圖的廣度遍歷,定義一個隊列即可。

第17題:
題目:在一個字符串中找到第一個只出現一次的字符。如輸入abaccdeff,則輸出b。  
分析:這道題是2006年google的一道筆試題。

 定義一個128長的數組(每個字符按ASCII碼對應相應的數組元素),初值爲0。遍歷字符串,把數組相應的位置上的數加1,第二次遍歷字符串時,讀數組上的數,爲1的則爲所求。實際上就是用數組做了個哈希表。


第18題:
題目:n個數字(0,1,…,n-1)形成一個圓圈,從數字0開始,
每次從這個圓圈中刪除第m個數字(第一個爲當前數字本身,第二個爲當前數字的下一個數字)。
當一個數字刪除後,從被刪除數字的下一個繼續刪除第m個數字。
求出在這個圓圈中剩下的最後一個數字。
July:我想,這個題目,不少人已經 見識過了。

 約瑟夫問題,模擬實現,記得求餘就可以。聽說還有O(n)算法,


第19題:
題目:定義Fibonacci數列如下:  
  / 0 n=0
f(n)= 1 n=1
  / f(n-1)+f(n-2) n=2

輸入n,用最快的方法求該數列的第n項。
分析:在很多C語言教科書中講到遞歸函數的時候,都會用Fibonacci作爲例子。
因此很多程序員對這道題的遞歸解法非常熟悉,但....呵呵,你知道的。。

 循環吧,從第1項開始計算,一直到n。還有一種更省事的方法,求出通項。

如果沒記錯通項應該是f(n)= (((sqrt(5)+1)/2)^n-((sqrt(5)-1)/2)^n) /sqrt(5)

第20題:
題目:輸入一個表示整數的字符串,把該字符串轉換成整數並輸出。
例如輸入字符串"345",則輸出整數345。

 字符串一個個取。每次取之前把現有的數(初值爲0)乘10再加上每個字符減48即爲現有的新數。同時注意正負號。

第21
2010年中興面試題
編程求解:
輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數,
使其和等於 m ,要求將其中所有的可能組合列出來.

 這是一個01揹包問題。同時加入一個二維輔助數組,記錄每次選擇的情況。K!輕描淡寫幾句話,這題挺累人的,特別是求所有組合,得分析那個輔助數組。

第22題:
有4張紅色的牌和4張藍色的牌,主持人先拿任意兩張,再分別在A、B、C三人額頭上貼任意兩張牌,
A、B、C三人都可以看見其餘兩人額頭上的牌,看完後讓他們猜自己額頭上是什麼顏色的牌,
A說不知道,B說不知道,C說不知道,然後A說知道了。
請教如何推理,A是怎麼知道的。
如果用程序,又怎麼實現呢?

 紅計0,藍計1。首輪三個人都沒猜出來,那麼每個人就不可能看到四個0或四個1。

對首輪最後一個人C來說,他應該看出來三個人至少有一個人頭上出現01,否則必定有人首輪能猜出,而C最終沒猜出,所以01必定出現在AB至少一個頭上。A如果看到B是00或11,則必能猜到自己是01,這是一種可能,不是充分條件。還有其他可能嗎?

覺得出題人沒表述清楚,題中說“然後A知道”,那麼BC是否知道呢?BC如果知道是否是因爲A知道了他們才知道的呢?這都會影響後續的結果。如果我答題,就蒙A一紅一藍。

編程實現,窮舉可能可以實現吧。
第23題:
用最簡單,最快速的方法計算出下面這個圓形是否和正方形相交。"  
3D座標系 原點(0.0,0.0,0.0)
圓形:
半徑r = 3.0
圓心o = (*.*, 0.0, *.*)

正方形:
4
個角座標;  
1:(*.*, 0.0, *.*)
2:(*.*, 0.0, *.*)
3:(*.*, 0.0, *.*)
4:(*.*, 0.0, *.*)

 圓的方程可以寫出,如果正方形的四個點代入圓的方程都大於0或是都小於則認爲不相交,其餘情況認爲二者相交。

第24題:
鏈表操作,
(1).單鏈表就地逆置,

聲明三個指針分別指向當前節點,下一節點,下下節點,從頭到尾換指針就可以。
(2)合併鏈表

 想怎麼合併?如果是排好序的兩個鏈表合成一個排好序的。分別比較兩個鏈表當前取到的值即可,誰小把指針指向誰,被指的鏈表,指針向前推繼續比,直到一個表遍歷到尾,再把它的尾指針直接指向未遍歷到尾的表的剩餘部分。

第25題:
寫一個函數,它的原形是int continumax(char*outputstr,char *intputstr)
功能:
在字符串中找出連續最長的數字串,並把這個串的長度返回,
並把這個最長數字串付給其中一個函數參數outputstr所指內存。
例如:"abcd12345ed125ss123456789"的首地址傳給intputstr後,函數將返回9,
outputstr所指的值爲123456789

 遍歷唄,遇到非數字無視,每次遇到新數字開始計數,而定義某一指針永遠指向長度最大的數字開始位置。

26.左旋轉字符串

題目:
定義字符串的左旋轉操作:把字符串前面的若干個字符移動到字符串的尾部。

如把字符串abcdef左旋轉2位得到字符串cdefab。請實現字符串左旋轉的函數。
要求時間對長度爲n的字符串操作的複雜度爲O(n),輔助內存爲O(1)。

 每個字符的位置是可以計算的,必定是當前位置(0起始)+總長度-2,算出來不小於總長度,則再減去一個總長度即可。

27.跳臺階問題
題目:一個臺階總共有n級,如果一次可以跳1級,也可以跳2級。
求總共有多少總跳法,並分析算法的時間複雜度。

這道題最近經常出現,包括MicroStrategy等比較重視算法的公司
都曾先後選用過個這道題作爲面試題或者筆試題。

 動態規劃,f(n)=f(n-1)+f(n-2)、f(1)=1、f(0)=1。

28.整數的二進制表示中1的個數
題目:輸入一個整數,求該整數的二進制表達中有多少個1。
例如輸入10,由於其二進制表示爲1010,有兩個1,因此輸出2。

分析:
這是一道很基本的考查位運算的面試題。
包括微軟在內的很多公司都曾採用過這道題。

 和1做與操作,如果結果爲1計數加1,再右移,直到數字等於0。

29.棧的push、pop序列
題目:輸入兩個整數序列。其中一個序列表示棧的push順序,
判斷另一個序列有沒有可能是對應的pop順序。
爲了簡單起見,我們假設push序列的任意兩個整數都是不相等的。 

比如輸入的push序列是1、2、3、4、5,那麼4、5、3、2、1就有可能是一個pop系列。
因爲可以有如下的push和pop序列:
push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,
這樣得到的pop序列就是4、5、3、2、1。
但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。

 模擬實現即可

30.在從1到n的正數中1出現的次數
題目:輸入一個整數n,求從1到n這n個整數的十進制表示中1出現的次數。

例如輸入12,從1到12這些整數中包含1 的數字有1,10,11和12,1一共出現了5次。
分析:這是一道廣爲流傳的google面試題。

 有點難度,不過可以窮舉。當然還是應該按不同位數求出分段函數表達式來,再找規律。

31.華爲面試題:
一類似於蜂窩的結構的圖,進行搜索最短路徑(要求5分鐘)

 怎麼個蜂窩法?無圖無真相。可能用迪傑斯特拉算法或是拓撲排序就行。

32.
有兩個序列a,b,大小都爲n,序列元素的值任意整數,無序;
要求:通過交換a,b中的元素,使[序列a元素的和]與[序列b元素的和]之間的差最小。
例如:  
var a=[100,99,98,1,2, 3];
var b=[1, 2, 3, 4,5,40];

 二維揹包問題。把所有數加起來再求一半。實際上就是求最接近和一半的序列,這個序列長度還得是n。就是說包的容量爲n,可承重量爲和的一半,每個物品的價值等於其重量,求價值最大的方案。
33.
實現一個挺高級的字符匹配算法:
給一串很長字符串,要求找到符合要求的字符串,例如目的串:123
1******3***2 ,12*****3這些都要找出來
其實就是類似一些和諧系統。。。。。

 通配符問題?參考第8題。
34.
實現一個隊列。
隊列的應用場景爲:
一個生產者線程將int類型的數入列,一個消費者線程將int類型的數出列

 PV原語問題?關鍵是控制線程同步。一次只能入列一個數,入列的同時不能出列,出列同時不入列,出列也只能一次一個。
35.
求一個矩陣m*n中最大的二維矩陣 (元素和最大).如:
1 2 0 3 4
2 3 4 5 1
1 1 5 3 0
中最大的是:
4 5
5 3
要求:(1)寫出算法;(2)分析時間複雜度;(3)用C寫出關鍵代碼

 遍歷一遍,先只計算每個元素和其下面的元素的和,再遍歷一遍,把每個元素計算的值與後一個元素計算的值相加,同時取最大值即爲所求。時間應該爲n*(m-1)+(n-1)(m-1),也就是O(mn)。

第36題-40題(有些題目蒐集於CSDN上的網友,已標明):
36.引用自網友:longzuo
谷歌筆試:
n支隊伍比賽,分別編號爲0,1,2。。。。n-1,已知它們之間的實力對比關係,
存儲在一個二維數組w[n][n]中,w[i][j] 的值代表編號爲i,j的隊伍中更強的一支。

所以w[i][j]=i 或者j,現在給出它們的出場順序,並存儲在數組order[n]中,
比如order[n] = {4,3,5,8,1......},那麼第一輪比賽就是 4對3, 5對8。.......
勝者晉級,敗者淘汰,同一輪淘汰的所有隊伍排名不再細分,即可以隨便排,
下一輪由上一輪的勝者按照順序,再依次兩兩比,比如可能是4對5,直至出現第一名

編程實現,給出二維數組w,一維數組order 和 用於輸出比賽名次的數組result[n],
求出result。

 編程模擬即可

37.
有n個長爲m+1的字符串,
如果某個字符串的最後m個字符與某個字符串的前m個字符匹配,則兩個字符串可以聯接,
問這n個字符串最多可以連成一個多長的字符串,如果出現循環,則返回錯誤。

 先把各個字符串看成節點,前後可匹配的就首尾相聯,形成DAG圖,再求用拓撲序列求最長路徑,沒有完整的拓撲序列就報錯出現循環。

38.
百度面試:
1.
用天平(只能比較,不能稱重)從一堆小球中找出其中唯一一個較輕的,使用x次天平,
最多可以從y個小球中找出較輕的那個,求y與x的關係式。

用一次天平可稱出三個小球,用兩次天平可稱三個三即九個,用次可稱三個九,y=3^x

2.有一個很大很大的輸入流,大到沒有存儲器可以將其存儲下來,
而且只輸入一次,如何從這個輸入流中隨機取得m個記錄。

應該知道輸入流的大小吧,然後分m次輸入,每次隨機生成一個小於m的整數,取該次輸入中相應的數據。

3.大量的URL字符串,如何從中去除重複的,優化時間空間複雜度

 遍歷一遍,用散列表記錄數量,對應的散列表位置爲空則記下該串,並該串散列表位置上自增。

39.
網易有道筆試:
(1).
求一個二叉樹中任意兩個節點間的最大距離,
兩個節點的距離的定義是 這兩個節點間邊的個數,
比如某個孩子節點和父節點間的距離是1,和相鄰兄弟節點間的距離是2,優化時間空間複雜度。

參見第11

(2).
求一個有向連通圖的割點,割點的定義是,如果除去此節點和與其相關的邊,
有向圖不再連通,描述算法。

 圖的割點問題,深度優先遍歷,如果某點的所有子孫節點與其祖先節點之間沒有相連的邊。

40.百度研發筆試題
引用自:zp155334877
1)設計一個棧結構,滿足一下條件:min,push,pop操作的時間複雜度爲O(1)。

參見第2

2)一串首尾相連的珠子(m個),有N種顏色(N<=10),
設計一個算法,取出其中一段,要求包含所有N中顏色,並使長度最短。
並分析時間複雜度與空間複雜度。

模擬實現即可。

先不考慮環,只考慮線性的情況。

申請一數組記錄當前所包含的顏色的數量。兩個指針,i指向起點,j移動。噹噹前顏色數爲N時,即形成一種方案,記錄當前長度,j停止移動,而移動i,相應去除i指向的顏色數量減一。減後數量不爲0就一直向前移,直到碰到一個減完後爲0,則說明此時顏色已不全了。此時繼續移動j,直到下一次顏色數爲N,如此反覆,移動j後每次顏色數爲N時,記錄當前方案長度,保留最小長度即爲所求。

如果帶環呢?環不環的只是多一個求餘問題。(已編碼驗證)

3)設計一個系統處理詞語搭配問題,比如說中國 和人民可以搭配,
則中國人民 人民中國都有效。要求:

  *系統每秒的查詢數量可能上千次;
  *
詞語的數量級爲10W;
  *每個詞至多可以與1W個詞搭配

當用戶輸入中國人民的時候,要求返回與這個搭配詞組相關的信息。

感覺問題與前面舉的例子挨不上。什麼叫搭配詞組相關的信息?中國、人民、人民中國、中華人民共和國……都可以算嗎?憑一些猜想試着寫幾句。

詞庫肯定得排序或建索引,方便查找。搭配信息也應該有相應的數據結構,比如用圖來存儲,無論是鄰接表還是鄰接陣保證有序。

再對給定詞語先做分詞,把詞語分出來,怎麼分呢?假設詞語最少兩個字,當然是每兩個字地截取輸入串,到詞庫裏去查。如果查出是某字的前綴,就再讀下面的字進一步查詞,直至匹配到,或查得完全不是個詞。對截串原則上使用貪心,一方面按最長匹配,另一方面匹配上了,直接取後兩個字進行匹配,未匹配上就從第二個字開始再取一個認爲是一個詞到詞庫裏去查。由此題題意,應該不考慮未匹配上的詞,也就是說用貪心必定能匹配上。如果只考慮問題“中國人民”,則可分成兩個詞中國、人民。

分好了詞,對分出的詞排序,再讀匹配信息,也就是取得了一個由若干節點構成的一張有向圖。在中國的節點上能找到人民的話,則說明二者可匹配,說明可以進行詞語組合,即得到中國人民和人民中國。

對同時輸入更多的詞,分詞工作並不是很難,關鍵是匹配怎麼輸出?如果只兩兩匹配,就兩兩組合輸出,如果是多詞匹配就得考慮組合的種類了(不考慮)。

另外分析一下性能:

詞應該兩個字的據多,四個字節,假設平均5個字節,10W個詞不超過0.5M。搭配信息用圖來存,10W個詞每個詞至多可以與1W個詞搭配,鄰接表按每位存一個搭配不超過120M,用字節存則要1G左右。因此空間上是可以接受的。如果用鄰接陣存則是不到鄰接表5倍(本來是10倍,但可以用上三角陣存儲,取半)。

時間上分詞主要用排好序了的二分查找或用索引,很方便。分出n個詞排好序後,進行匹配信息的查詢,只需n^2/2次圖查找,用鄰接陣可一次定位,用鄰接表每次查找也可以用二分查找。

一次應用大概是nlog10W+nlogn+n^2/2*log1W(鄰接表則不乘最後的log1W)。代入一些數值計算後,一般的PC機,1秒鐘可以不低於一千次應用,時間上應該可以達標。

41.求固晶機的晶元查找程序
晶元盤由數目不詳的大小一樣的晶元組成,晶元並不一定全佈滿晶元盤,

照相機每次這能匹配一個晶元,如匹配過,則拾取該晶元,
若匹配不過,照相機則按測好的晶元間距移到下一個位置。
求遍歷晶元盤的算法 求思路。

 沒太看明白

42.請修改append函數,利用這個函數實現:

兩個非降序鏈表的並集,1->2->3 和 2->3->5 併爲 1->2->3->5
另外只能輸出結果,不能修改兩個鏈表的數據。

 參見24

43.遞歸和非遞歸倆種方法實現二叉樹的前序遍歷。

 遞歸時先輸出再調左右的子問題。非遞歸就用循環加棧,初始根節點進棧,然後每次從棧中取一個指針,再把它的右節點左節點先後進棧。

44.騰訊面試題:
1.
設計一個魔方(六面)的程序。

應該不是讓求魔方的解法,求魔方解法也是有公式的,不同的情況按分支套公式就行。

依題意可能是讓實現一個模擬魔方的程序。不討論UI,只討論魔方算法的實現。

六個3*3矩陣,各矩陣初值內部相同兩兩間互不相同,對應每個面。

魔方轉動只有爲兩種:正對該面時順時針轉動或逆時針轉動。

先聲明各面排列,比如1對3、2對4、5對6。因爲魔方的主要操作是對某面轉動,所以爲了儘量的快應該直接使用分支判斷。寫六個分支對應六個面,每面再寫兩個分支(順時針轉、逆時針轉)。每種轉動,自己和相鄰面的矩陣數據如何交換。只對矩陣進行更新,再把更新後的矩陣返回到UI,即實現了魔方的轉換。

2.有一千萬條短信,有重複,以文本文件的形式保存,一行一條,有重複。
請用5分鐘時間,找出重複出現最多的前10條。

遍歷同時用哈希表計數,每更新一次哈希表計數,試着更新大小爲10的小根堆,求數量最大的10條。

3.收藏了1萬條url,現在給你一條url,如何找出相似的url。(面試官不解釋何爲相似)

什麼叫相似?是指屬於同一服務,還是指URL字串上大都相同呢?

先考慮前者,如果一個URL是另一個URL的前綴,是不是應該叫相似?或者兩個URL的前面的目錄相同,是不是也應該叫相似?所以可以先左對齊求前段地址和部分目錄的字符串是否一致,如果一致則認爲相似。

再考慮後者,如果不滿足前面的結果。考慮相似是指匹配字符較多。那就用動態規劃求字符對齊匹配數最大的。那麼較多是多少呢?這個標準可以人爲取,我想怎麼也得80%以上才叫相似吧。那就人爲規定了字符動態匹配數的標準了,達標的就認爲是相似的。

45.雅虎:
1.對於一個整數矩陣,存在一種運算,對矩陣中任意元素加一時,需要其相鄰(上下左右)

某一個元素也加一,現給出一正數矩陣,判斷其是否能夠由一個全零矩陣經過上述運算得到。

這是一個最大流問題,把矩陣看成黑白相間的點陣,題目等價於,每次對相鄰黑白兩點數量加1

先判斷黑白點上各自的數據和是否相等,如果二者數據不等,就沒必要往下進行了,必定無解。

如果相等,再轉化最大流來解。假設存在一個源點指向所有的黑點每條邊的容量爲黑點上的數據,又有一個匯點,所有白點都聯向它,其邊上的容量也爲無窮大。所有黑點指向與其相鄰的白點,其容量爲白點上的數據。求從源到匯的最大流,如果最後源的所有邊都飽和,即最大流等於黑點上數據之和則說明該矩陣有解。
2.一個整數數組,長度爲n,將其分爲m份,使各份的和相等,求m的最大值
  比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1; 
  {3,6}{2,4,3} m=2
  {3,3}{2,4}{6} m=3 所以m的最大值爲3

 m的值不可能超過sum(a)/max(ai)。從sum(a)/max(ai)到1開始試,同時m得是sum(a)的因子。

再轉成01揹包問題。包容量爲sum(a)/m,每個物品價值等於其體積,求包可裝最大價值的方

特別地,如果sum(a)是素數,而數組內存在不等的兩個數,則m只能爲1。


46.搜狐:
四對括號可以有多少種匹配排列方式?比如兩對括號可以有兩種:()()和(())

14

()()()()  (()())()  ()(()())(())()()  ()(())()  ()()(())  (())(())

((()))()  ()((()))  (((()))) (()()())  ((())())  (()(())) ((()()))

卡特蘭數


47.創新工場:
求一個數組的最長遞減子序列 比如{9,4,3,2,5,4,3,2}的最長遞減子序列爲{9,5,4,3,2}

 經典的動態規劃問題。f(i)=max{f(j)}+1 (當j<i且a[i]<a[j])。如果使用二分查找,理論上會更快。

48.微軟:
一個數組是由一個遞減數列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移兩位形成的,在這種數組中查找某一個數。

 二分查找吧。雖然左移了若干位,不影響用二分查找。只是判斷向前還是向後查找時注意一下該段起中尾三個數的大小關係。

49.一道看上去很嚇人的算法面試題:
如何對n個數進行排序,要求時間複雜度O(n),空間複雜度O(1)

 這題八成是蒙人的,數學上都證明了用比較排序是不可能達到O(n)的。這題讓達到這個時間,必定是要討論數組的狀況,比如範圍不大可以使用計數排序,再如只有整數可以使用基數排序,等等一些特殊情況才能在線性時間內完成排序。

50.網易有道筆試:
1.
求一個二叉樹中任意兩個節點間的最大距離,兩個節點的距離的定義是 這兩個節點間邊的個數,
比如某個孩子節點和父節點間的距離是1,和相鄰兄弟節點間的距離是2,優化時間空間複雜度。

參見39題。

2.求一個有向連通圖的割點,割點的定義是,
如果除去此節點和與其相關的邊,有向圖不再連通,描述算法。

參見39題。
-------------------------------------------------------------------


51.
和爲n連續正數序列。
題目:輸入一個正數n,輸出所有和爲n連續正數序列。

例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以輸出3個連續序列1-5、4-6和7-8。
分析:這是網易的一道面試題。

 等差數列n=(2*a1*x+(x-1)x)/2,a1爲首項,x爲長度,x從1開始自增到n反求a1,如果求出a1爲正整數則是一個可行序列,輸出。時間應該是O(n)。


52.
二元樹的深度。

題目:輸入一棵二元樹的根結點,求該樹的深度。

從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度爲樹的深度。

例如:輸入二元樹:
                                           10
                                         /     /
                                       6        14
                                     /         /   /
                                   4         12     16

輸出該樹的深度3

二元樹的結點定義如下:

struct SBinaryTreeNode // a node of the binary tree
{
     int              m_nValue; // value of node
      SBinaryTreeNode  *m_pLeft;  // leftchild of node
      SBinaryTreeNode  *m_pRight; // right childof node
};
分析:這道題本質上還是考查二元樹的遍歷。

 動態規劃,High(i)=max{high(i->left),high(i->right)}+1,本質上是後序遍歷。

53.字符串的排列。
題目:輸入一個字符串,打印出該字符串中字符的所有排列。
例如輸入字符串abc,則輸出由字符a、b、c所能排列出來的所有字符串
abc、acb、bac、bca、cab和cba。

分析:這是一道很好的考查對遞歸理解的編程題,
因此在過去一年中頻繁出現在各大公司的面試、筆試題中。

  經典的排列輸出。得考慮一種情況,如果字符串內有重複字符怎麼辦,所以不能用全排列的算法,得用不重複排列算法。

54.調整數組順序使奇數位於偶數前面。

題目:輸入一個整數數組,調整數組中數字的順序,使得所有奇數位於數組的前半部分,
所有偶數位於數組的後半部分。要求時間複雜度爲O(n)。

 兩頭掃,左邊碰到偶數就停,再掃右邊,右邊碰到奇數就跟左邊的偶數換,再繼續掃左邊,直至兩邊相碰。類似快速排序的一種實現方式。

55.
題目:類CMyString的聲明如下:
class CMyString
{
public:
      CMyString(char* pData = NULL);
      CMyString(const CMyString& str);
      ~CMyString(void);
      CMyString& operator = (const CMyString&str);

private:
      char* m_pData;
};
請實現其賦值運算符的重載函數,要求異常安全,即當對一個對象進行賦值時發生異常,對象的狀態不能改變。

 C++不太懂。

56.最長公共字串。

題目:如果字符串一的所有字符按其在字符串中的順序出現在另外一個字符串二中,

則字符串一稱之爲字符串二的子串。

注意,並不要求子串(字符串一)的字符必須連續出現在字符串二中。
請編寫一個函數,輸入兩個字符串,求它們的最長公共子串,並打印出最長公共子串。

例如:輸入兩個字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它們的最長公共子串,
則輸出它們的長度4,並打印任意一個子串。

分析:求最長公共子串(Longest Common Subsequence, LCS)是一道非常經典的動態規劃題,

因此一些重視算法的公司像MicroStrategy都把它當作面試題。

 經典動態規劃

a[i]=b[i]時,f(i,j)=f(i-1,j-1)+1.

a[i]!=b[i]時,f(i,j)=max{f(i-1,j), f(i,j-1)}


57.
用倆個棧實現隊列。

題目:某隊列的聲明如下:

template<typename T> class CQueue
{
public:
      CQueue() {}
      ~CQueue() {}

      void appendTail(const T&node);  // append a element to tail
      voiddeleteHead();              // remove a element from head

private:
     T> m_stack1;
     T> m_stack2;
};

分析:從上面的類的聲明中,我們發現在隊列中有兩個棧。
因此這道題實質上是要求我們用兩個棧來實現一個隊列。
相信大家對棧和隊列的基本性質都非常瞭解了:棧是一種後入先出的數據容器,
因此對隊列進行的插入和刪除操作都是在棧頂上進行;隊列是一種先入先出的數據容器,
我們總是把新元素插入到隊列的尾部,而從隊列的頭部刪除元素。

 AB兩個棧,存數時先把B棧的數出棧依次放到A中,取數時先把A棧的數出棧依次放到B中。


58.
從尾到頭輸出鏈表。

題目:輸入一個鏈表的頭結點,從尾到頭反過來輸出每個結點的值。鏈表結點定義如下:
struct ListNode
{

     int       m_nKey;
      ListNode* m_pNext;
};
分析:這是一道很有意思的面試題。
該題以及它的變體經常出現在各大公司的面試、筆試題中。

 用棧輸出。也可以用遞歸,先調子問題再輸出本節點。


59.
不能被繼承的類。
題目:用C++設計一個不能被繼承的類。

分析:這是Adobe公司2007年校園招聘的最新筆試題。
這道題除了考察應聘者的C++基本功底外,還能考察反應能力,是一道很好的題目。

 final?C++不太懂。

 

60.在O(1)時間內刪除鏈表結點。

題目:給定鏈表的頭指針和一個結點指針,在O(1)時間刪除該結點。鏈表結點的定義如下:

struct ListNode

{

     int        m_nKey;

      ListNode*  m_pNext;

};

函數的聲明如下:
void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);

分析:這是一道廣爲流傳的Google面試題,能有效考察我們的編程基本功,還能考察我們的反應速度,

更重要的是,還能考察我們對時間複雜度的理解。

把下一節點的值拷到本節點,再刪下一節點。

-------------------------------------------------------------------------

 

61.找出數組中兩個只出現一次的數字
題目:一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。
請寫程序找出這兩個只出現一次的數字。要求時間複雜度是O(n),空間複雜度是O(1)。

分析:這是一道很新穎的關於位運算的面試題。

先求異或得出一個結果是這兩個數字的異或,必不爲0。其二進制至少有一位爲1,以這位爲準把原數組分爲兩部分,一部分該位爲1數,一部分該位爲0數。這兩個數必分別在這兩個小數組裏,且每個小數組除此數之外其他數出現兩次,再用異或就可以分別求得。


62.
找出鏈表的第一個公共結點。
題目:兩個單向鏈表,找出它們的第一個公共結點。

鏈表的結點定義爲:
struct ListNode

{

     int         m_nKey;

      ListNode*   m_pNext;

};

分析:這是一道微軟的面試題。微軟非常喜歡與鏈表相關的題目,
因此在微軟的面試題中,鏈表出現的概率相當高。

 見第7


63.
在字符串中刪除特定的字符。
題目:輸入兩個字符串,從第一字符串中刪除第二個字符串中所有的字符。

例如,輸入”They are students.”和”aeiou”,

則刪除之後的第一個字符串變成”Thy r stdnts.”

分析:這是一道微軟面試題。在微軟的常見面試題中,與字符串相關的題目佔了很大的一部分,
因爲寫程序操作字符串能很好的反映我們的編程基本功。

 從頭到尾掃,每個字符都與第二個串中的所有字符比較,相同就略去。O(mn)

64. 尋找醜數。
題目:我們把只包含因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,
但14不是,因爲它包含因子7。習慣上我們把1當做是第一個醜數。
求按從小到大的順序的第1500個醜數。

分析:這是一道在網絡上廣爲流傳的面試題,據說google曾經採用過這道題。

  每一醜數必定是其前面某個數直接乘2、3、5所得。從第一個開始算到第1500個就行。每次算一個,把該次要計算的數之前所有醜數乘以2、3、5,算出來之後的所有結果與此前最後一個醜數比較,大於最後一個醜數且最小即爲要取的醜數。爲了確保不溢出有必要使用64位計算。取幾個數最小值的時候用堆應該可以更快一些,那就得建個小根堆。算出來是859963392。(已編碼驗證)


65.
輸出1到最大的N位數
題目:輸入數字n,按順序輸出從1最大的n位10進制數。比如輸入3,

則輸出1、2、3一直到最大的3位數即999。
分析:這是一道很有意思的題目。看起來很簡單,其實裏面卻有不少的玄機。

 有啥玄機?從1輸出到10^n-1不就成了,注意別溢出就成了。

66.顛倒棧。
題目:用遞歸顛倒一個棧。例如輸入棧{1, 2, 3, 4, 5},1在棧頂。
顛倒之後的棧爲{5, 4, 3, 2, 1},5處在棧頂。

F(i,bool)//bool==1表示出棧,0表示進棧

{

if(bool==1){

F(i-1,1);

i出棧;

}else{

F(i-1,0);

i進棧;

}

}

Main(){F(5,1);F(5,0);}

 

67.倆個閒玩娛樂。

1.撲克牌的順子
從撲克牌中隨機抽5張牌,判斷是不是一個順子,即這5張牌是不是連續的。
2-10爲數字本身,A爲1,J爲11,Q爲12,K爲13,而大小王可以看成任意數字。

遍歷一遍,看有幾張王,且除王外最大最小值。

無王時,最大最小差爲4

一王時,最大最小差爲3

倆王時,最大最小差爲2

2.n個骰子的點數。
把n個骰子扔在地上,所有骰子朝上一面的點數之和爲S。輸入n,
打印出S的所有可能的值出現的概率。

 一個骰子六面。最小全是一,S=n;最大全是六,S=6n。那麼S的取值應該是n至6n的所有整數。

對首尾的概率好計算,都是(1/6)^n,其他取值不容易求解。

分析一下,對某一S,其所有可能的情形,就是n個數,每個數取值在1~6之間,把這些數拼成S。問題類似多重揹包問題,包大小爲S,物品大小爲1,價值爲1,n個物品,每個物品個只有6個,求價值最大的方案總數。不同的是對所有方案必須每件物品至少裝一件,那麼這個多重揹包就改成:包大小爲S-6,物品大小爲1,價值爲1,n個物品,每個物品個只有5個,求價值最大的方案總數。

同時注意到n+1與6n-1的概率應該是一樣的,n+2與6n-2也一樣……因此,計算量可以減少一半。

因此, S從n+1遍歷到7n/2,對每個S解上面的多重揹包問題,對某S求得的方案數除以6^n即爲其概率。

不太困難,只是複雜度高點。


68.把數組排成最小的數。
題目:輸入一個正整數數組,將它們連接起來排成一個數,輸出能排出的所有數字中最小的一個。
例如輸入數組{32,  321},則輸出這兩個能排成的最小數字32132。
請給出解決問題的算法,並證明該算法。

分析:這是09年6月份百度的一道面試題,
從這道題我們可以看出百度對應聘者在算法方面有很高的要求。

 這題有點意思,應該是道經典題,以前見過類似的,不過當時只認識了題目關鍵所在,沒有思考解決方案。一般可以先按字符串大小排序,貪心輸出。但關鍵在於,如果一個數(32)是另一數(321)的前綴(32),且後綴(1)比前綴(32)小。簡單地按貪心輸出來的數可能不是最小的。對此問題可以如下解決:

如果1號數(排好序了)是2號數的前綴,且2號數的後綴比前綴小(比前綴大則直接把1號數輸出了),則向下掃描。如果2號數是3號數前綴,且3號數的後綴比前綴小,繼續,直到i號數不是i+1號數的前綴或i+1號數前綴比後綴小。輸出i號數(就認爲刪了)。再看i+1號數是否是i-1的前綴且i+1號數的後綴比前綴小,如果是則重複上面的過程,如果不是則輸出i-1號數(就認爲刪了)。如此依次執行就可以實現。

測試數據:35 351 3512 35124 3522 3523


69.旋轉數組中的最小元素。
題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個排好序的數組的一個旋轉,

輸出旋轉數組的最小元素。例如數組{3, 4, 5, 1, 2}爲{1, 2, 3, 4, 5}的一個旋轉,該數組的最小值爲1。

   分析:這道題最直觀的解法並不難。從頭到尾遍歷數組一次,就能找出最小的元素,
時間複雜度顯然是O(N)。但這個思路沒有利用輸入數組的特性,我們應該能找到更好的解法。

 二分查找。先取首尾兩數比較,如果首小於尾,則第一個數即爲所求。如果首大於尾,二分查找得到一個新數,把原數組分爲兩段。總取首大於尾的那段(取後段首指針加1、取前段爲尾指針減1),新指針對比,如果首小於尾或者首尾指針重疊,首指針所指爲所求,否則重複二分查找迭代。


70.
給出一個函數來輸出一個字符串的所有排列。
ANSWER
簡單的回溯就可以實現了。當然排列的產生也有很多種算法,去看看組合數學,

還有逆序生成排列和一些不需要遞歸生成排列的方法。
印象中Knuth的<TAOCP>第一卷裏面深入講了排列的生成。這些算法的理解需要一定的數學功底,
也需要一定的靈感,有興趣最好看看。

參照第53
71.數值的整數次方。

題目:實現函數double Power(double base, int exponent),求base的exponent次方。
不需要考慮溢出。

分析:這是一道看起來很簡單的問題。可能有不少的人在看到題目後30秒寫出如下的代碼:
double Power(double base, int exponent)
{

      double result = 1.0;
      for(int i = 1; i <= exponent; ++i)
            result *=base;
      return result;
}

上面給出的算法不是我給的,可以算出結果,這種做法效率不是很好,讓人一看就是不是正規軍出身。體現水平的解法應該是用循環或遞歸實現:x^y={(x^(y/2))^2 、y爲偶數時|x*(x^(y/2))^2 、y爲奇數時}

  

72.
題目:設計一個類,我們只能生成該類的一個實例。
分析:只能生成一個實例的類是實現了Singleton模式的類型。

 C++不太懂,是不是得定義靜態變量然後在構造函數裏動點手腳?

 
73.
對策字符串的最大長度。

題目:輸入一個字符串,輸出該字符串中對稱的子字符串的最大長度。
比如輸入字符串“google”,由於該字符串裏最長的對稱子字符串是“goog”,因此輸出4。

分析:可能很多人都寫過判斷一個字符串是不是對稱的函數,這個題目可以看成是該函數的加強版。

 掃描啊,如果碰到連續兩個一樣的字母,就另外左右開弓的掃,求出對稱的長度同時更新最大值。再繼續向前掃,直至字符串掃完。


74.數組中超過出現次數超過一半的數字

題目:數組中有一個數字出現的次數超過了數組長度的一半,找出這個數字。

分析:這是一道廣爲流傳的面試題,包括百度、微軟和Google在內的多家公司都
曾經採用過這個題目。要幾十分鐘的時間裏很好地解答這道題,
除了較好的編程能力之外,還需要較快的反應和較強的邏輯思維能力。

 從頭掃,前後兩個指針,初始時只動後指針向後移,如果兩個指針指向不同的數字,則兩個數字都刪除,遇到相同的數字,後指針向後移。掃完後剩下的數必定一樣且是所求的數。

 

75.二叉樹兩個結點的最低共同父結點
題目:二叉樹的結點定義如下:
struct TreeNode
{

   int m_nvalue;
    TreeNode* m_pLeft;
    TreeNode* m_pRight;
};

輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。
分析:求數中兩個結點的最低共同結點是面試中經常出現的一個問題。這個問題至少有兩個變種。

 從根開始後序遍歷,至某個節點時,開始記數爲0,每向上走一層記數減1,向下走一層記數加1,同時記錄記數最小值,當遇到另一個節點時,繼續遍歷記數,當記數值更新到前面記錄的最小值時,當前節點即爲最近共同祖先。思路比較簡單,編碼得好好設計一下。


76.
複雜鏈表的複製

題目:有一個複雜鏈表,其結點除了有一個m_pNext指針指向下一個結點外,
還有一個m_pSibling指向鏈表中的任一結點或者NULL。其結點的C++定義如下:
 struct ComplexNode
{
    int m_nValue;
    ComplexNode* m_pNext;
    ComplexNode* m_pSibling;
};

下圖是一個含有5個結點的該類型複雜鏈表。
圖中實線箭頭表示m_pNext指針,虛線箭頭表示m_pSibling指針。爲簡單起見,
指向NULL的指針沒有畫出。                                 
請完成函數ComplexNode* Clone(ComplexNode* pHead),以複製一個複雜鏈表。 
分析:在常見的數據結構上稍加變化,這是一種很新穎的面試題。
要在不到一個小時的時間裏解決這種類型的題目,我們需要較快的反應能力,
對數據結構透徹的理解以及紮實的編程功底。

 如果僅僅是爲了複製一個鏈表還是不困難的。首先遍歷一遍所有節點,把每個節點的值都抹掉,當然不是真抹,按序存在別處,用從0開始的數字自增寫入原鏈表。新分配一塊連續的節點空間用來存儲新複製後的鏈表,這樣每個節點的物理位置是可以由首地址計算出來的,同時遍歷原鏈表可以得到每個節點與哪些節點相連,再在新鏈表上把各節點與其相連節點的地址算出來,把指針指向它即可。 


77.
關於鏈表問題的面試題目如下:

1.給定單鏈表,檢測是否有環。
 使用兩個指針p1,p2從鏈表頭開始遍歷,p1每次前進一步,p2每次前進兩步。如果p2到達鏈表尾部,
說明無環,否則p1、p2必然會在某個時刻相遇(p1==p2),從而檢測到鏈表中有環。

2.給定兩個單鏈表(head1, head2),檢測兩個鏈表是否有交點,如果有返回第一個交點。

參見第7
3.給定單鏈表(head),如果有環的話請返回從頭結點進入環的第一個節點。

參見第7
4.
只給定單鏈表中某個結點p(並非最後一個結點,即p->next!=NULL)指針,刪除該結點。

見第60

5.只給定單鏈表中某個結點p(非空結點),在p前面插入一個結點。

再它後面加一個節點,把它的值拷到新加的節點中。
 

78.鏈表和數組的區別在哪裏?

分析:主要在基本概念上的理解。
但是最好能考慮的全面一點,現在公司招人的競爭可能就在細節上產生,
誰比較仔細,誰獲勝的機會就大。

一般都是線性的,存儲空間鏈表是不連續的數組是連續的。檢索的時候數組可以隨機檢索,鏈表只能順序檢索。增刪改查操作的時間複雜度不一樣。

 
79.
1.
編寫實現鏈表排序的一種算法。說明爲什麼你會選擇用這樣的方法?

插入排序可能會好點,插入新節點時時間複雜度爲O(1)
2.編寫實現數組排序的一種算法。說明爲什麼你會選擇用這樣的方法?

快排、堆排、歸併都可以,時間上差不多,同時各有各的好處。
3.請編寫能直接實現strstr()函數功能的代碼。

KMP算法
 

80.阿里巴巴一道筆試題

問題描述:
12個高矮不同的人,排成兩排,每排必須是從矮到高排列,而且第二排比對應的第一排的人高,問排列方式有多少種?
這個筆試題,很YD,因爲把某個遞歸關係隱藏得很深。

 定義一個有序數組0~11,0表示該人排在前排,1表示該人排在後排。只要確定了數組元素的值是0還是1,就必定能確定一種排序方案。這是因爲六個0或1必須保證從小到大排列,而這排列只有一種。

數組爲000000111111 表示方案:

1  2 3  4  5

7  8 9  10 11

數組爲010011010011 表示方案:

2  3 6  8  9

4  5 7  10 11

那麼問題就變爲求六個0六個1的不重複排列,同時保證,每個1前面的0的數量大於1的數量。因此這變成一個不重複排列數的問題。

最後求得方案總數爲132(已編碼驗證)

先來幾組百度的面試題:

===================

81.第1組百度面試題
1.一個int數組,裏面數據無任何限制,要求求出所有這樣的數a[i],
其左邊的數都小於等於它,右邊的數都大於等於它。
能否只用一個額外數組和少量其它空間實現。

從左到右掃,邊掃邊更新當前遇到所有元素的最大值。比如說遇到i,此時最大值就是i,則把最大值更新,且把額外數組i位置上的置1。

再從右往左掃,邊掃邊更新當前遇到所有元素的最大值。對額外數組對應位置上爲1的數據,比如j對應額外數組爲1,拿最大值與j比較,此時最大值就是j,則把最大值更新,且認爲j就是一個所求元素。

2.一個文件,內含一千萬行字符串,每個字符串在1K以內,
要求找出所有相反的串對,如abc和cba。

用HASH。設字符串從左到右讀出,匹配一個標識1,其逆串標識0。下面開始:

對每個字符串先到HASH裏查是否存在,如果不存在,把自己和標識1放入HASH,同時它的逆轉和標識0放入HASH。如果存在,且標識爲1,說明以前遇見過相同的字符串,忽略這個字符串。如果存在且標識爲0,說明有與它對稱的字符串,把相應的標識從0改爲1,而該字符串和其逆串爲一個所求串對。

複雜度爲:遍歷每個串,只對不重複出現的串求逆串。空間上可能是一個較大的HASH

3.STL的set用什麼實現的?爲什麼不用hash?

 SET裏不會出現相同的元素,HASH裏可以出現相同元素。假如用兩層HASH,即HASH再HASH,就可以實現SET那樣去除相同元素。

或者SET前先HASH一下,如果存在相同的數據,則不另HASH而直接指向它。

具體STL裏的SET是怎麼實現的不太清楚。

82.第2組百度面試題
1.給出兩個集合A和B,其中集合A={name},
集合B={age、sex、scholarship、address、...},
要求:
問題1、根據集合A中的name查詢出集合B中對應的屬性信息;

關鍵是建好A與B的映射關係,AB都設自己ID,且按ID有序排列,然後把ID匹配好都扔到HASH表裏頭吧。如果不想設ID直接匹配也行,把AB以兩個不同的匹配對象扔到HASH裏面,開銷大點就是。
問題2、根據集合B中的屬性信息(單個屬性,如age<20等),查詢出集合A中對應的name。

最簡單的考慮當然是把它扔DB裏頭,一條SELECT就可以實現。

或者存文件裏,對文件建索引。

或者對待查屬性排好序,遍歷或二分查找,不過數據量一大,效率就太低。

至於具體算法的實現就要考慮多些了。如果只按單個屬性查詢的話,可以對不同的屬性建多個不同線段樹,不同屬性的線段樹可以實現按不同屬性的區間取值。如果想實現多個屬性一起查詢用線段樹可能就有點困難,但也不是沒法實現,效率不好說。不知道多維線段樹能不能實現多個屬性一起查詢,沒用過,這些都是傳說中的高級數據結構。

2.給出一個文件,裏面包含兩個字段{url、size},
即url爲網址,size爲對應網址訪問的次數,
要求:
問題1、利用Linux Shell命令或自己設計算法,
查詢出url字符串中包含“baidu”子字符串對應的size字段值;

grep baidu file.txt | awk '{print $2}'

設計算法的話,只能讀文件挨行掃描,用KMP匹配,如果成功則輸出size
問題2、根據問題1的查詢結果,對其按照size由大到小的排列。
(說明:url數據量很大,100億級以上)

 先對查詢出的size排好序,快排就可以,特別地,排序的同時記錄每一個size排序前後的位置。

掃描文件,生成相應多的指針,對每個size被查詢出來的URL安放一個指針,然後逐次做交換(1放到8,8放到13,13放到9……)。對這種大數據量的題,減少掃描就是對複雜度的最好保證。

83.第3組百度面試題
1.今年百度的一道題目
百度筆試:給定一個存放整數的數組,重新排列數組使得數組左邊爲奇數,右邊爲偶數。
要求:空間複雜度O(1),時間複雜度爲O(n)。

見第54

2.百度筆試題
用C語言實現函數void * memmove(void *dest, const void *src, size_t n)。
memmove函數的功能是拷貝src所指的內存內容前n個字節到dest所指的地址上。
分析:
由於可以把任何類型的指針賦給void類型的指針
這個函數主要是實現各種數據類型的拷貝。

 語法不太懂。

84.第4組百度面試題
2010年3道百度面試題[相信,你懂其中的含金量]
1.a~z包括大小寫與0~9組成的N個數
用最快的方式把其中重複的元素挑出來。

 用哈希表。也可以定義一個128長的數組(每個字符按ASCII碼對應相應的數組元素)。

.已知一隨機發生器,產生0的概率是p,產生1的概率是1-p,現在要你構造一個發生器,
使得它構造0和1的概率均爲1/2;構造一個發生器,使得它構造1、2、3的概率均爲1/3;...,
構造一個發生器,使得它構造1、2、3、...n的概率均爲1/n,要求複雜度最低。

對n=2,認爲01表示0、10表示1,等概率,其他情況放棄

對n=3,認爲001表示1、010表示2,100表示3,等概率,其他情況放棄

對n=4,認爲0001表示1、0010表示2,0100表示3,1000表示4,等概率,其他情況放棄

……

3.有10個文件,每個文件1G,
每個文件的每一行都存放的是用戶的query,每個文件的query都可能重複。
要求按照query的頻度排序.

 可以用HASH來保存不同query的頻度,再把HASH按頻度排序,按頻度排好序的HASH每個query依次按頻度次數寫入文件,每至1G就寫下一個文件,直至10個文件寫完。這個要求HASH表足夠大,還要能快速對HASH表內的數據進行排序。

85.又見字符串的問題
1.
給出一個函數來複制兩個字符串A和B。
字符串A的後幾個字節和字符串B的前幾個字節重疊。
分析:記住,這種題目往往就是考你對邊界的考慮情況。

想實現什麼樣的複製,A->B?遍歷到尾,從尾開始往回拷貝。
2.已知一個字符串,比如asderwsde,尋找其中的一個子字符串比如sde的個數,
如果沒有返回0,有的話返回子字符串的個數。

 KMP算法
86.
怎樣編寫一個程序,把一個有序整數數組放到二叉樹中?
分析:本題考察二叉搜索樹的建樹方法,簡單的遞歸結構。
關於樹的算法設計一定要聯想到遞歸,因爲樹本身就是遞歸的定義。

而,學會把遞歸改稱非遞歸也是一種必要的技術。
畢竟,遞歸會造成棧溢出,關於系統底層的程序中不到非不得以最好不要用。
但是對某些數學問題,就一定要學會用遞歸去解決。

 關鍵是想放到一個什麼樣樹裏頭,一個所有節點只有右節點的樹也叫二叉樹。

如果放一個高度最低的二叉查找樹,按二分法查找,同時前序生成一棵二叉樹。

87.

1.大整數數相乘的問題。(這是2002年在一考研班上遇到的算法題)

大數乘法,模擬豎乘計算的實現,乘數每一位與被乘數相乘,其積乘以10的冪,冪次爲該位在原乘數裏的倍數。再累加。累加也可能用到大數相加,也是模擬豎加計算實現。
2.求最大連續遞增數字串(如“ads3sl456789DF3456ld345AA”中的“456789”)

掃描一遍,記錄遞增起始點,每次遞增序列結束,記錄最長長度。令一指針永遠指向長度最大的遞增序列。
3.實現strstr功能,即在父串中尋找子串首次出現的位置。
(筆試中常讓面試者實現標準庫中的一些函數)

 KMP算法


88.2005
年11月金山筆試題。編碼完成下面的處理函數。
函數將字符串中的字符'*'移到串的前部分,

前面的非'*'字符後移,但不能改變非'*'字符的先後順序,函數返回串中字符'*'的數量。
如原始串爲:ab**cd**e*12,
處理後爲*****abcde12,函數並返回值爲5。(要求使用盡量少的時間和輔助空間)

 捨得用空間的話,就開闢一個同樣大小的字符串,掃一遍把非星寫進來,同時記錄n個數,再把原數組前n位置爲星,n+1位起把新拼成的串賦回來。

省點空間的話就定義一個小數組,記錄每個星的位置,總長度n。遍歷從1開始原串,遇到非星字符,到小數組中二分查找,找出有多少個星在其後,用當前下標加上找出的星的數量,即爲其目標位置。再取目標位置上原來的數進行迭代,當某點後不再有星迴到原串位置1的下一個位置即2開始迭代,直至原始串前n個字符都迭代完畢,串即整理完畢。

再想省空間就得移多次,可能會耗點時。

89.神州數碼、華爲、東軟筆試題
1.2005年11
月15日華爲軟件研發筆試題。實現一單鏈表的逆轉。

見第8題。。
2.
編碼實現字符串轉整型的函數(實現函數atoi的功能),據說是神州數碼筆試題。如將字符
串 ”+123”123,”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0

CS是什麼意思?atoi的實現參照第20題。如果CS表示冗餘字符,則遇到非數字或首位的加減號則停。
3.快速排序(東軟喜歡考類似的算法填空題,又如堆排序的算法等)

隨便一本講排序的書上都有介紹
4.
刪除字符串中的數字並壓縮字符串。
如字符串”abc123de4fg56”處理後變爲”abcdefg”。注意空間和效率。
(下面的算法只需要一次遍歷,不需要開闢新空間,時間複雜度爲O(N))

遇到數字就記錄其位置,繼續往後碰到字符就覆蓋數字的位置,然後繼續,字符串完了,就把最後數字的位置上寫’/0’
5.求兩個串中的第一個最長子串(神州數碼以前試題)。
如"abractyeyt","dgdsaeactyey"的最大子串爲"actyet"。

 動態規劃。

f[i][j]表示到ai,bj公共最長子串長度

s[i][j]表示以ai,bj結尾的連續公共子串長度

s[i][j]=f[i][j]=0;

a[i]==b[i]時、s[i][j]=s[i-1][j-1]+1 f[i][j]=max{s[i][j]、f[i-1][j-1]}

a[i]!=b[i]時、f[i][j]=max{f[i-1][j]、f[i][j-1]};(已編碼驗證)

90.

1.不開闢用於交換數據的臨時空間,如何完成字符串的逆序
(
在技術一輪面試中,有些面試官會這樣問)。

參照第8題。誰說交換數據一定得臨時空間?a=a+b;b=a-b;a=a-b;
2.刪除串中指定的字符
(做此題時,千萬不要開闢新空間,否則面試官可能認爲你不適合做嵌入式開發)

參照89
3.判斷單鏈表中是否存在環。

 參照第7

91.
1.
一道著名的毒酒問題
有1000桶酒,其中1桶有毒。而一旦吃了,毒性會在1周後發作。
現在我們用小老鼠做實驗,要在1周內找出那桶毒酒,問最少需要多少老鼠。

把1000轉爲二進制,需十位,所以選十隻老鼠編好號,分別對應每位。每位上是1的對應那隻老鼠喝該桶酒。比如第6桶,對應110,二號三號老鼠喝這桶酒。最後把十個老鼠一排,死了的被認爲1,未死的是0,讀出這個十位二進制,即爲有毒的桶號。
2.有趣的石頭問題
有一堆1萬個石頭和1萬個木頭,對於每個石頭都有1個木頭和它重量一樣,
把配對的石頭和木頭找出來。

 如果只能比較重量大小,先對石頭排序,再拿木頭到石頭裏二分查找。複雜度爲O(nlogn)

如果能稱出重量,就把所有重量稱出,重量相同的匹配,有點類似於用哈希表了。雖說像HASH表,但人工操作的時候,還是得排序才能找到重量相同的。

 

92.
1.
多人排成一個隊列,我們認爲從低到高是正確的序列,但是總有部分人不遵守秩序。
如果說,前面的人比後面的人高(兩人身高一樣認爲是合適的),
那麼我們就認爲這兩個人是一對“搗亂分子”,比如說,現在存在一個序列:
176, 178, 180, 170, 171
這些搗亂分子對爲
<176, 170>, <176, 171>, <178, 170>, <178, 171>,<180, 170>, <180, 171>, 
那麼,現在給出一個整型序列,請找出這些搗亂分子對的個數(僅給出搗亂分子對的數目即可,不用具體的對)

要求:
輸入:
爲一個文件(in),文件的每一行爲一個序列。序列全爲數字,數字間用”,”分隔。
輸出:
爲一個文件(out),每行爲一個數字,表示搗亂分子的對數。

詳細說明自己的解題思路,說明自己實現的一些關鍵點。
並給出實現的代碼 ,並分析時間複雜度。
限制:
輸入每行的最大數字個數爲100000個,數字最長爲6位。程序無內存使用限制。

 所謂搗亂分子,就是求逆序對。最直接地,借用歸併排序,歸併時發生交換則記數。更高級的做法,可以用樹狀數組。

93.在一個int數組裏查找這樣的數,它大於等於左側所有數,小於等於右側所有數。
直觀想法是用兩個數組a、b。a[i]、b[i]分別保存從前到i的最大的數和從後到i的最小的數,

一個解:這需要兩次遍歷,然後再遍歷一次原數組,
將所有data[i]>=a[i-1]&&data[i]<=b[i]的data[i]找出即可。

給出這個解答後,面試官有要求只能用一個輔助數組,且要求少遍歷一次。

 見第81

 

94.微軟筆試題
求隨機數構成的數組中找到長度大於=3的最長的等差數列
輸出等差數列由小到大: 
如果沒有符合條件的就輸出
格式:
輸入[1,3,0,5,-1,6]
輸出[-1,1,3,5]
要求時間複雜度,空間複雜度儘量小

 實現起來不是很複雜。先排序,再求兩個數的差,如果它們是等差數列,那麼必定能寫出第三個數,如果在序列中存在第三個數,則是一個等差數列,再查第四個數,直至找不到下一個數,記錄長度公差起始點。長度有更長的,則更新記錄。可能複雜度高點,不知道有沒有較高效的解法。(已編碼驗證)

95.華爲面試題

1 判斷一字符串是不是對稱的,如:abccba

兩頭夾挨個比,直到兩指針相碰或發現兩個字符不等。
2.用遞歸的方法判斷整數組a[N]是不是升序排列

 f(n)遞增:{a[n]大於a[n-1];f[n-1]遞增}

96.08年中興校園招聘筆試題
1
.編寫strcpy 函數
已知strcpy 函數的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。不調用C++/C 的字符串庫函數,請
編寫函數 strcpy

 挨個字符拷,遇’/0’停止。


最後壓軸之戲,終結此微軟等100題系列V0.1版。
那就,
連續來幾組微軟公司的面試題,讓你一次爽個夠:
======================
97.第1組微軟較簡單的算法面試題
1.編寫反轉字符串的程序,要求優化速度、優化空間。 

參照第8
2.
在鏈表裏如何發現循環鏈接?

參照第7
3.
編寫反轉字符串的程序,要求優化速度、優化空間。

參照第8
4.
給出洗牌的一個算法,並將洗好的牌存儲在一個整形數組裏。 

洗牌關鍵是隨機性。比如54張牌按概率1/54生成一張放在數組首位,再按1/53在剩餘53張牌生成放在下一位。

隨機函數可以調用標準庫。原數組共54個數,每生成一個就把生成的數與最後一個交換,然後隨機數範圍減一,這樣就不用刪除原數組元素同時又能保證剩餘元素的隨機性。
5.寫一個函數,檢查字符是否是整數,如果是,返回其整數值。
(或者:怎樣只用4行代碼編寫出一個從字符串到長整形的函數?)

參照20
98.第2組微軟面試題
1.給出一個函數來輸出一個字符串的所有排列。

參照第53
2.請編寫實現malloc()內存分配函數功能一樣的代碼。

語法不太懂,參照一下標準庫吧。
3.給出一個函數來複制兩個字符串A和B。字符串A的後幾個字節和字符串B的前幾個字節重疊。 

參見第85
4.怎樣編寫一個程序,把一個有序整數數組放到二叉樹中? 
參見第86
5.怎樣從頂部開始逐層打印二叉樹結點數據?請編程。 
參見第16
6.怎樣把一個鏈表掉個順序(也就是反序,注意鏈表的邊界條件並考慮空鏈表)?

參見第8題。對空鏈表單獨處理。
99.第3組微軟面試題
1.燒一根不均勻的繩,從頭燒到尾總共需要1個小時。
現在有若干條材質相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢?

拿三根繩。第一根燒兩頭,第二根燒一頭,第一根燒完則過了30分鐘,第二根同時點另一頭,燒完第二根則過了15分鐘,再燒第三根,兩頭點,燒完又過了30分鐘。加一起一小時十五分鐘。

2.你有一桶果凍,其中有黃色、綠色、紅色三種,閉上眼睛抓取同種顏色的兩個。

抓取多少個就可以確定你肯定有兩個同一顏色的果凍?(5秒-1分鐘) 

4
3.如果你有無窮多的水,一個3公升的提捅,一個5公升的提捅,兩隻提捅形狀上下都不均勻,
問你如何才能準確稱出4公升的水?(40秒-3分鐘) 

有N種方法,就是求二元一次方程整數解3X+5Y=4。

把5公升桶水到至3公升桶裏,還剩2公升,3公升桶倒幹,把2公升倒至3公升桶,再裝滿5公升倒滿3公升桶,剩4公升水。
一個岔路口分別通向誠實國和說謊國。
來了兩個人,已知一個是誠實國的,另一個是說謊國的。
誠實國永遠說實話,說謊國永遠說謊話。現在你要去說謊國,
但不知道應該走哪條路,需要問這兩個人。請問應該怎麼問?(20秒-2分鐘)

“如果我問他左邊這條路到說謊國,他會告訴我是。是這樣嗎?”

對方回答“是”,則這條路通誠實國,反之則通說謊國。
100.第4組微軟面試題,挑戰思維極限
1.12個球一個天平,現知道只有一個和其它的重量不同,問怎樣稱才能用三次就找到那個球。

第一步分三份,每份四個,稱一次可以找出那份不同的。

第二步取任意兩個稱,如果相同,再找一個換掉其中一個稱。如果還相同,則未稱的是有問題的,第二次稱不同,則新拿進來的是有問題的球。如果第一次稱就不同,換一個稱,如果相同則拿掉的那個是有問題的,如果不同沒拿下來的那個有問題。

13個呢?(注意此題並未說明那個球的重量是輕是重,所以需要仔細考慮)(5分鐘-1小時) 

分成445,先稱44。

如果一樣,問題球在5中。任取三個,再取三個正常球,如果平衡則剩下兩個中存在一個有問題,拿其中一個與一個正常球比即可。如果不平衡可知取得的三個球必有一重(或輕)。三球中任取兩個稱,相等則剩下的球爲問題球,不等則重的(或輕的)即爲所求。

如果不一樣,44分左重右輕兩組,左邊去除三留一,再加上右邊取三個過來組成左邊四個球,右邊剩一個加上三個正常球。如果相等,則左邊去除的三個球必定有一重球,再一次可求得這個球。如果左邊重,則左邊原來留下的球爲問題球。如果左邊高起右邊低下,則從右邊取來的三球中必有一輕球,再一次可求得這個球。

2.在9個點上畫10條直線,要求每條直線上至少有三個點?(3分鐘-20分鐘) 

座標:(0,0)、(2,0)、(4,0)、(1,1)、(1,2)、(1,3)、(0,2)、(2,2)、(4,2)
3.在一天的24小時之中,時鐘的時針、分針和秒針完全重合在一起的時候有幾次?
都分別是什麼時間?你怎樣算出來的?(5分鐘-15分鐘)

兩次。0點和12點

 

終結附加題:
微軟面試題,挑戰你的智商
==========
說明:如果你是第一次看到這種題,並且以前從來沒有見過類似的題型,
並且能夠在半個小時之內做出答案,說明你的智力超常..)
1.第一題 . 五個海盜搶到了100顆寶石,每一顆都一樣大小和價值連城。他們決定這麼分: 
抽籤決定自己的號碼(1、2、3、4、5) 
                          
首先,由1號提出分配方案,然後大家表決,當且僅當超過半數的人同意時,
按照他的方案進行分配,否則將被扔進大海喂鯊魚 
如果1號死後,再由2號提出分配方案,然後剩下的4人進行表決,
當且僅當超過半數的人同意時,按照他的方案進行分配,否則將被扔入大海喂鯊魚。

依此類推 
條件:每個海盜都是很聰明的人,都能很理智地做出判斷,從而做出選擇。
問題:第一個海盜提出怎樣的分配方案才能使自己的收益最大化?

 著名的海盜分金問題。

如果只剩下45,那麼無論4提出什麼方案,5必定反對,所以4爲了保命,無論如何也不會讓他前面的人死完。

那麼3就可以利用這一點,以(100.0.0)的方案分配,由於4爲了保命,必定支持,而5的反對無效,於是超過半數同意。

2應該知道3的方案,他要想通過自己的方案必須三個人同意,於是他要拉攏45兩個人,同時爲了自己利潤最大化,他考慮只各給一枚就可以保證他們同意,因爲此方案45得利大於3號所給方案。於是2的方案是(98.0.1.1)。

1也知道2的方案,他要想通過自己的方案,必須另兩個人同意,於是考慮拉攏34或35或45。於是對應方案應該是(97.0.1.2.0)、(97.0.1.0.2)、(96.0.0.2.2)。顯然,1的最優方案是前兩種。

2.一道關於飛機加油的問題,已知: 
每個飛機只有一個油箱,  
飛機之間可以相互加油(注意是相互,沒有加油機)  
一箱油可供一架飛機繞地球飛半圈, 
問題:
爲使至少一架飛機繞地球一圈回到起飛時的飛機場,至少需要出動幾架飛機?
(所有飛機從同一機場起飛,而且必須安全返回機場,不允許中途降落,中間沒有飛機場) 

五架飛機。首先地球是圓的,可以反向飛行。先起動三架,到1/8處,3把12加滿,3返航;;到1/4處,2把1加滿,2返航;到1/2處,反向起動4;到3/4處,14相遇,4給1加1/4箱油,4返航,此時反向起動5;到7/8處,145相遇,5給14各加1/4箱油,5返航;最後一起回到起點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章