算法面試題彙總(更新中)

原題網址:http://www.cnblogs.com/xwdreamer/archive/2011/12/13/2296910.htmlhtml

1.把二元查找樹轉變成排序的雙向鏈表
題目:
輸入一棵二元查找樹,將該二元查找樹轉換成一個排序的雙向鏈表。
要求不能建立任何新的結點,只調整指針的指向。
   10
  / \
  6  14
/ \ / \
4  8 12 16
轉換成雙向鏈表
4=6=8=10=12=14=16。java

思路彙總:node

(1)每訪問到一個parent,遞歸左子樹,遞歸右子樹,鏈接左子樹的最左邊,右子樹的最右邊與根節點的結合處。故遞歸函數必須標明當前子樹左右狀況。面試

(2)中序遍歷樹,記錄一個pre,而後每訪問到一個節點,就將其加入雙向鏈表中,具體即爲與pre的操做。算法

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

思路彙總:數組

(1)在棧內部定義兩個實際的棧結構,一個棧存放主體數據,另外一個棧存放當前最小值,入棧和出棧操做時,同時更新最小值棧。緩存

 

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

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

思路彙總:

(1)用動態規劃思想,定義六個變量:maxStart=0,maxEnd=0,maxSum=a[0],tmpStart=0,tmpEnd=0,tmpSum=a[0]。從頭遍歷整個數組。

若是tmpSum>maxSum then tmp->max; 若是tmpSum<=0; tmpSum=0;tmpStart = tmpEnd = now-index.  輸出maxStart-maxEnd

 

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

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

思路彙總:

(1)用動態規劃的思想作,全局建一個緩存的TreeNode的數組,便於輸出路徑,遞歸地將sum往下傳,過程當中減去通過節點的val,當sum<0,遞歸終止,當sum==0,且葉節點時

輸出緩存數組,並提出數組中當前節點,並返回。當sum>0時,分別遞歸當前節點的非null左子樹和右子樹。

 

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

思路彙總:

(1)能夠用size爲k的堆來作

(2)能夠用快排的partion來作。

 

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

思路彙總:http://blog.csdn.net/heaven13483/article/details/7925621

 

第7題
微軟亞院之編程判斷倆個鏈表是否相交
給出倆個單向鏈表的頭指針,好比h1,h2,判斷這倆個鏈表是否相交。
爲了簡化問題,咱們假設倆個鏈表均不帶環。

問題擴展:
1.若是鏈表可能有環列?
2.若是須要求出倆個鏈表相交的第一個節點列?

思路彙總:

(1)讓h1和h2都遍歷到最後一個節點,判斷最後節點是否相同。

(2)讓其中一個鏈表h1遍歷到最後一個節點,並將最後一個節點鏈接到h2上,變爲判斷鏈表是否有環的問題。

擴展問題1.先判斷是否有環,將環點處解開。擴展問題2.與找環點一樣的思路。

環問題:fast,slow指針,fast速度2,slow速度1.第一次相遇必定在環上。再分別從h1表頭和相遇點等速前進,相交點爲入口點。

 

第8題
此貼選一些 比較怪的題,,因爲其中題目自己與算法關係不大,僅考考思惟。特此並做一題。
1.有兩個房間,一間房裏有三盞燈,另外一間房有控制着三盞燈的三個開關,

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

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

3. ★用一種算法來顛倒一個連接表的順序。如今在不用遞歸式的狀況下作一遍。
★用一種算法在一個循環的連接表裏插入一個節點,但不得穿越連接表。
★用一種算法整理一個數組。你爲何選擇這種方法?
★用一種算法使通用字符串相匹配。
★顛倒一個字符串。優化速度。優化空間。
★顛倒一個句子中的詞的順序,好比將「我叫克麗絲」轉換爲「克麗絲叫我」,

實現速度最快,移動最少。
★找到一個子字符串。優化速度。優化空間。
★比較兩個字符串,用O(n)時間和恆量空間。
★假設你有一個用1001個整數組成的數組,這些整數是任意排列的,可是你知道全部的整數都在1到1000(包括1000)之間。此外,除一個數字出現兩次外,其餘全部數字只出現一次。假設你只能對這個數組作一次處理,用一種算法找出重複的那個數字。若是你在運算中使用了輔助的存儲方式,那麼你能找到不用這種方式的算法嗎?
★不用乘法或加法增長8倍。如今用一樣的方法增長7倍。

思路彙總:(待分析)

 

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

例如輸入五、七、六、九、十一、十、8,因爲這一整數序列是以下樹的後序遍歷結果:

         8
      /  \
     6    10
    / \  / \
   5  7 9  11
所以返回true。
若是輸入七、四、六、5,沒有哪棵樹的後序遍歷的結果是這個序列,所以返回false。

思路彙總:

(1)遞歸地檢查BSTreeCheck(int[] a, int start, int end),a[end]是根節點。知足,數組能被分爲兩部分,左部分不大於根,右部分不小於根。

 

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

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

思路彙總:

(1)用split(),返回數組。而後倒序輸出

 

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

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

思路彙總:

(1)寫一個遞歸函數,全局存一個最大距離,初始化爲-1,遞歸函數返回一個數組,當前節點最大深度,當前節點最大距離,遞歸函數內部將當前節點左子樹最大深度+右子樹最大深度與左右子樹最大距離比較,再與全局最大距離比較。

最終全局存放的最大距離爲最大距離。(當前節點往上一個節點返回時,別忘了算上本身對深度的貢獻)

 

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

思路彙總:http://www.cnblogs.com/lzmfywz/archive/2013/04/22/3036370.html

java中能夠利用&&短路  boolean tmp = (n > 0) && (addFun(n-1)!=0);

 

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

思路彙總:先定義一個first指針走k步,若是k步以前到null返回null。而後定義一個second指針從頭開始,與first同時繼續前進,直到first所指的節點爲tail節點(或next爲null)。

 

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

思路彙總:

設置兩個index: start = 0,end = a.length-1; 而後while(start<end){若是sum>15,end- - ,若是sum<15,end+ +,else 輸出a[start] 和a[end] 而且break}。

 

第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
};

思路彙總:

(1)遞歸方法:從根節點遞歸,互換left和right

(2)循環方法: 須要一個輔助棧,將根節點壓棧。循環條件爲棧非空,取出棧頂節點,左右互換,將子節點入棧。

 

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

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

輸出8 6 10 5 7 9 11。

思路彙總:

(1)輔助隊列來作

 

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

思路彙總:

(1)256大小的int數組,遍歷字符串,更新數組內容,再次遍歷字符串,找到第一個個數不爲一的字符。O(n)的時間複雜度。

 

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

思路彙總:

(1)http://www.360doc.com/content/12/0314/13/1429048_194255548.shtml

(2)鏈表作

 

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

輸入n,用最快的方法求該數列的第n項。
分析:在不少C語言教科書中講到遞歸函數的時候,都會用Fibonacci做爲例子。
思路彙總:

(1)遞歸的方法,最屌絲了。

(2)迭代的方法,維護一個f(n-1)和f(n-2)的緩存。

 

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

思路彙總:

用動態規劃的思想,維護一個緩存數組,和一個index(其實就是能夠維護一個棧),從n到1遍歷,依次入棧,知足條件後或者沒法繼續遞歸下去後,pop棧頂元素。這樣就能獲得各類組合。

組合的條件能夠不少種,好比能夠設定組合條件爲固定數目的整數的組合,這樣,能夠判斷棧大小。本題的組合條件就是和爲m,那麼每當有整數入棧時,從m中剔除這個值,並將調整後的m遞歸傳遞

給下一個函數,直到m=0時,輸出棧中全部元素,並pop棧頂元素。m<0,直接pop。(注意:本題由於是動態規劃的思想,有重疊最小子問題,因此用的是棧思想,可是實際是用一個緩存數組和index)

 

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

思路彙總:

牌的組合有:rb,rr,bb這三種,進行全羅列。(程序實現的思路有待思考)

 

第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, *.*)

思路彙總:

算出四個點離圓形最近的兩個點,算圓心到兩點組成直線的距離是否小於r。

http://blog.csdn.net/bitzhuxb/article/details/8641636

 

第24題:
鏈表操做,
(1).單鏈表就地逆置,
(2)合併鏈表

思路彙總:

(1)題:用三個指針,pre,cur,next

(2)題:p1,p2,cur

 

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

思路彙總:

相似於第三題,維護(maxStart,maxEnd,maxLen),遍歷字符串,跟新(tmpStart,tmpEnd,tmpLen),若是tmpLen>maxLen,更新max三個值。

 

26.左旋轉字符串

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

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

思路彙總:

1.寫一個針對字符串逆置的函數,reverse(),這樣若是將須要左旋的字符串爲AB,左旋的部分爲A,那麼能夠reverse(A);reverse(B);reverse(AB);

其中,reverse()函數的的時間複雜度爲O(n),空間複雜度爲O(1)。

 

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

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

思路分析:

f(n) = f(n-1)+f(n-2);

 

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

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

思路彙總:

設定一個mask = 1, 而後不斷mask<<1,直至mask爲0,其間,用每一次得到的mask & 給定的數,得到相應位置上的值爲1仍是0,統計count

 

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

思路彙總:

創建一個棧,將push序列的數不斷push到棧中,這能夠算作一個shift操做,而後每一步都比較棧頂元素與pop序列的第一個元素,若是相同,就pop棧,而且刪除pop序列第一個元素,這能夠定義爲reduce操做。

當push序列爲空,棧爲空,且pop序列爲空時,返回true,不然返回false

 

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

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

思路彙總:分別對最高位,中間位,最低位進行分析,分別分析他們是0,1,或者大於1的狀況 http://blog.sina.com.cn/s/blog_3fc85e260100mbss.html

 

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];

思路分析:

窮舉法: (複雜度很大,並且存在被交換到另外一邊的元素又再次被交換回來的風險)

首先先計算a,b中元素和之間的差絕對值abs,而後逐一的把a中的元素和b中的任一元素做比較,若是它們交換後的差值絕對值abs小於原來的值abs,那麼就把a,b交換,並從新計算a和b的絕對值,

這種動做反覆的進行,直到a中任一的元素都不能和b中的任一元素交換爲止。

貪婪搜索:(O(n3),能夠證實不存在窮舉法中存在的問題)

當前數組a和數組b的和之差爲A = sum(a) - sum(b),a的第i個元素和b的第j個元素交換後,a和b的和之差爲
A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
     = sum(a) - sum(b) - 2 (a[i] - b[j])
      = A - 2 (a[i] - b[j])
    設x = a[i] - b[j],那麼

A'  = |A - 2x|,固然A' 越小也好,因此當x 在 (0,A)之間時,作這樣的交換才能使得交換後的a和b的和之差變小,x越接近A/2效果越好,若是找不到在(0,A)之間的x,則當前的a和b就是答案。

因此算法大概以下:在a和b中尋找使得x在(0,A)之間而且最接近A/2的i和j,交換相應的i和j元素,從新計算A後,重複前面的步驟直至找不到(0,A)之間的x爲止。

回溯法:(複雜度還不知道)

http://blog.csdn.net/ljsspace/article/details/6434621

 

33.
實現一個挺高級的字符匹配算法:
給一串很長字符串,要求找到符合要求的字符串,例如目的串:123
1******3***2 ,12*****3這些都要找出來

思路分析:

因爲此處都是ASSIC字符,因此能夠建一個256大小的bool數組,index是ASSIC字符碼,而後遍歷待匹配字符串統計,再遍歷bool數組看是否匹配模式字符串

 

34.
實現一個隊列。
隊列的應用場景爲:
一個生產者線程將int類型的數入列,一個消費者線程將int類型的數出列

思路分析:

java中可使用synchronized關鍵字,wait(),和notifyAll()方法。其中隊列是否爲空做爲消費者的判斷條件,隊列是否爲滿做爲生產者的判斷條件

相關文章
相關標籤/搜索