微軟的100道演算法面試題(終結版)

Java資訊庫發表於2018-08-29

前言

資料結構與演算法的重要性已不言而喻,最近,我整理出十大經典排序演算法、五大常用演算法總結,今天特意整理出微軟面試的100題,若有不足之處,歡迎指正!由於篇幅過長,前30道題目寫在上一篇,大家可以進我的個人主頁瀏覽,之後我會抽時間爭取把資料結構與演算法做成一個系列,敬請期待!

這裡寫圖片描述

31、和為n 連續正數序列

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

例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以輸出3 個連續序列1-5、4-6 和7-8。

32、二元樹的深度

題目:輸入一棵二元樹的根結點,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。

分析:這道題本質上還是考查二元樹的遍歷。

33、字串的排列

題目:輸入一個字串,列印出該字串中字元的所有排列。

例如輸入字串abc,則輸出由字元a、b、c 所能排列出來的所有字串abc、acb、bac、bca、cab 和cba。

分析:這是一道很好的考查對遞迴理解的程式設計題。

34、調整陣列順序使奇數位於偶數前面

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

35、最長公共字串

題目:如果字串一的所有字元按其在字串中的順序出現在另外一個字串二中,則字串一稱之為字串二的子串。注意,並不要求子串(字串一)的字元必須連續出現在字串二中。

請編寫一個函式,輸入兩個字串,求它們的最長公共子串,並列印出最長公共子串。

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

分析:求最長公共子串是一道非常經典的動態規劃題。

36、從尾到頭輸出連結串列

題目:輸入一個連結串列的頭結點,從尾到頭反過來輸出每個結點的值。

連結串列結點定義如下:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

37、在O(1)時間內刪除連結串列結點

題目:給定連結串列的頭指標和一個結點指標,在O(1)時間刪除該結點。

連結串列結點的定義如下:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

函式的宣告如下:

void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);

分析:這道題考察程式設計基本功和反應速度,更重要的是考察面試者對時間複雜度的理解。

38、找出陣列中兩個只出現一次的數字

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

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

39、找出連結串列的第一個公共結點

題目:兩個單向連結串列,找出它們的第一個公共結點。

連結串列的結點定義為:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

分析:這是一道微軟的面試題,在微軟的面試題中,連結串列出現的概率相當高。

40、在字串中刪除特定的字元

題目:輸入兩個字串,從第一字串中刪除第二個字串中所有的字元。例如,輸入”They are students.”和”aeiou”, 則刪除之後的第一個字串變成”Thy r stdnts.”。

分析:在微軟的常見面試題中,與字串相關的題目佔了很大的一部分,因為寫程式操作字串能很好的反映面試者的程式設計基本功。

41、 尋找醜數

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

42、輸出1 到最大的N 位數

題目:輸入數字n,按順序輸出從1 最大的n 位10 進位制數。比如輸入3,則輸出1、2、3 一直到最大的3 位數即999。

分析:這是一道很有意思的題目,看起來很簡單,其實裡面卻有不少的玄機。

43、顛倒棧

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

44、閒玩娛樂

(1)撲克牌的順子

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

(2)n 個骰子的點數。把n 個骰子扔在地上,所有骰子朝上一面的點數之和為S。輸入n,

列印出S 的所有可能的值出現的概率。

45、把陣列排成最小的數

題目:輸入一個正整數陣列,將它們連線起來排成一個數,輸出能排出的所有數字中最小的

一個。例如輸入陣列{32, 321},則輸出這兩個能排成的最小數字32132。

請給出解決問題的演算法,並證明該演算法。

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

46、旋轉陣列中的最小元素

題目:把一個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個

排好序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3, 4, 5, 1, 2}為{1, 2, 3, 4, 5}的一個旋轉,該陣列的最小值為1。

分析:這道題最直觀的解法並不難,我們應該利用輸入陣列的特性找到更好的解法。

47、數值的整數次方

題目:實現函式double Power(double base, int exponent),求base 的exponent 次方。

不需要考慮溢位。

48、 題目:設計一個類,我們只能生成該類的一個例項。

分析:只能生成一個例項的類是實現了Singleton 模式的型別。

49、對策字串的最大長度

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

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

加強版。

50、陣列中超過出現次數超過一半的數字

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

分析:這道面試題百度、微軟和Google 在內的多家公司都採用過,解答這道題除了較好的程式設計能力外,還需要較快的反應和較強的邏輯思維能力。

51、二叉樹兩個結點的最低共同父結點

題目:二叉樹的結點定義如下:

struct TreeNode

{

int m_nvalue;

TreeNode* m_pLeft;

TreeNode* m_pRight;

};

輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。

52、複雜連結串列的複製

題目:有一個複雜連結串列,其結點除了有一個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),以複製一個複雜連結串列。

53、關於連結串列問題的面試題目如下:

(1)給定單連結串列,檢測是否有環。

使用兩個指標p1,p2 從連結串列頭開始遍歷,p1 每次前進一步,p2 每次前進兩步。如果p2 到達連結串列尾部,說明無環,否則p1、p2 必然會在某個時刻相遇(p1==p2),從而檢測到連結串列中有環。

(2)給定兩個單連結串列(head1, head2),檢測兩個連結串列是否有交點,如果有返回第一個交點。如果head1==head2,那麼顯然相交,直接返回head1。否則,分別從head1,head2 開始遍歷兩個連結串列獲得其長度len1 與len2,假設len1>=len2,那麼指標p1 由head1 開始向後移動len1-len2 步,指標p2=head2,下面p1、p2 每次向後前進一步並比較p1p2 是否相等,如果相等即返回該結點,否則說明兩個連結串列沒有交點。

(3)給定單連結串列(head),如果有環的話請返回從頭結點進入環的第一個節點。

運用題一,我們可以檢查連結串列中是否有環。如果有環,那麼p1p2 重合點p 必然在環中。從p 點斷開環,方法為:p1=p, p2=p->next, p->next=NULL。此時,原單連結串列可以看作兩條單連結串列,一條從head 開始,另一條從p2 開始,於是運用題二的方法,我們找到它們的第一個交點即為所求。

(4)只給定單連結串列中某個結點p(並非最後一個結點,即p->next!=NULL)指標,刪除該結點。辦法很簡單,首先是放p 中資料,然後將p->next 的資料copy 入p 中,接下來刪除p->next即可。

(5)只給定單連結串列中某個結點p(非空結點),在p 前面插入一個結點。辦法與前者類似,首先分配一個結點q,將q 插入在p 後,接下來將p 中的資料copy 入q中,然後再將要插入的資料記錄在p 中。

54、連結串列和陣列的區別在哪裡?

分析:主要在基本概念上的理解,但是最好能考慮的全面一點。

55、(1)編寫實現連結串列排序的一種演算法。說明為什麼你會選擇用這樣的方法?

(2)編寫實現陣列排序的一種演算法。說明為什麼你會選擇用這樣的方法?

(3)請編寫能直接實現strstr()函式功能的程式碼。

56、阿里巴巴一道筆試題

**題目:**12 個高矮不同的人,排成兩排,每排必須是從矮到高排列,而且第二排比對應的第一排的人高,問排列方式有多少種?

57、百度面試題

(1)一個int 陣列,裡面資料無任何限制,要求求出所有這樣的數a[i],其左邊的數都小於等於它,右邊的數都大於等於它。能否只用一個額外陣列和少量其它空間實現。

(2)一個檔案,內含一千萬行字串,每個字串在1K 以內,要求找出所有相反的串對,如abc 和cba。

(3)STL 的set 用什麼實現的?為什麼不用hash?

58、百度面試題

題目:給定一個存放整數的陣列,重新排列陣列使得陣列左邊為奇數,右邊為偶數。

要求:空間複雜度O(1),時間複雜度為O(n)。

59、用C 語言實現函式void * memmove(void *dest, const void *src, size_t n)。memmove 函式的功能是拷貝src 所指的記憶體內容前n 個位元組到dest 所指的地址上。

分析:由於可以把任何型別的指標賦給void 型別的指標, 這個函式主要是實現各種資料型別的拷貝。

60、又見字串的問題

(1)給出一個函式來複制兩個字串A 和B。字串A 的後幾個位元組和字串B 的前幾個位元組重疊。分析:記住,這種題目往往就是考你對邊界的考慮情況。

(2)已知一個字串,比如asderwsde,尋找其中的一個子字串比如sde 的個數,如果沒有返回0,有的話返回子字串的個數。

61、怎樣編寫一個程式,把一個有序整數陣列放到二叉樹中?

分析:本題考察二叉搜尋樹的建樹方法,簡單的遞迴結構。關於樹的演算法設計一定要聯想到遞迴,因為樹本身就是遞迴的定義。

62、(1)大整數數相乘的問題。

(2)求最大連續遞增數字串(如“ads3sl456789DF3456ld345AA”中的“456789”)

(3)實現strstr 功能,即在父串中尋找子串首次出現的位置。

63、金山筆試題,編碼完成下面的處理函式。

題目:函式將字串中的字元’‘移到串的前部分,前面的非’‘字元後移,但不能改變非’‘字元的先後順序,函式返回串中字元’‘的數量。如原始串為:ab**cd**e*12,處理後為*****abcde12,函式並返回值為5。(要求使用盡量少的時間和輔助空間)

64、神州數碼、華為筆試題

(1)華為軟體研發筆試題,實現一單連結串列的逆轉。

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

(3)快速排序

(4)刪除字串中的數字並壓縮字串。如字串”abc123de4fg56”處理後變為”abcdefg”。注意空間和效率。

(5)求兩個串中的第一個最長子串。

如”abractyeyt”,”dgdsaeactyey”的最大子串為”actyet”。

65、(1)不開闢用於交換資料的臨時空間,如何完成字串的逆序

(2)刪除串中指定的字元

(3)判斷單連結串列中是否存在環。

66、一道著名的毒酒問題

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

67、有趣的石頭問題

有一堆1 萬個石頭和1 萬個木頭,對於每個石頭都有1 個木頭和它重量一樣,把配對的石頭和木頭找出來。

68、在一個int 陣列裡查詢這樣的數,它大於等於左側所有數,小於等於右側所有數。直觀想法是用兩個陣列a、b。a[i]、b[i]分別儲存從前到i 的最大的數和從後到i 的最小的數,一個解答。

69、微軟筆試題

求隨機數構成的陣列中找到長度大於=3 的最長的等差數列, 輸出等差數列由小到大,如果沒有符合條件的就輸出格式:

輸入[1,3,0,5,-1,6]

輸出[-1,1,3,5]

要求時間複雜度,空間複雜度儘量小。

70、華為面試題

(1)判斷一字串是不是對稱的,如:abccba。

(2)用遞迴的方法判斷整陣列a[N]是不是升序排列。

最後壓軸之戲,終結微軟公司的面試題:

第1 組微軟較簡單的演算法面試題

1、編寫反轉字串的程式,要求優化速度、優化空間。

2、在連結串列裡如何發現迴圈連結?

3、編寫反轉字串的程式,要求優化速度、優化空間。

4、給出洗牌的一個演算法,並將洗好的牌儲存在一個整形陣列裡。

5、寫一個函式,檢查字元是否是整數,如果是,返回其整數值。

(或者:怎樣只用4 行程式碼編寫出一個從字串到長整形的函式?)

第2 組微軟面試題

1、給出一個函式來輸出一個字串的所有排列。

2、請編寫實現malloc()記憶體分配函式功能一樣的程式碼。

3、給出一個函式來複制兩個字串A 和B。字串A 的後幾個位元組和字串B 的前幾個位元組重疊。

4、怎樣編寫一個程式,把一個有序整數陣列放到二叉樹中?

5、怎樣從頂部開始逐層列印二叉樹結點資料?請程式設計。

6、怎樣把一個連結串列掉個順序(也就是反序,注意連結串列的邊界條件並考慮空連結串列)?

第3 組微軟面試題

1、燒一根不均勻的繩,從頭燒到尾總共需要1 個小時。現在有若干條材質相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢?

2、你有一桶果凍,其中有黃色、綠色、紅色三種,閉上眼睛抓取同種顏色的兩個。抓取多少個就可以確定你肯定有兩個同一顏色的果凍?(5 秒-1 分鐘完成)

3、如果你有無窮多的水,一個3 公升的提捅,一個5 公升的提捅,兩隻提捅形狀上下都不均

勻,問你如何才能準確稱出4 公升的水?(40 秒-3 分鐘完成)

第4 組微軟面試題,挑戰思維極限

1、12 個球一個天平,現知道只有一個和其它的重量不同,問怎樣稱才能用三次就找到那個

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

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

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

微軟的100道演算法面試題到這裡就完結了!

最後

為了讓學習變得輕鬆高效, 現在給大家提供一個學習平臺,讓你在實踐中積累經驗掌握原理。主要方向是JAVA架構師,在這裡你可以學習Java工程化、高效能及分散式、深入淺出、效能調優、Spring,MyBatis,Netty原始碼分析和大資料等知識點。想要了解詳情的可以加入Java後端技術群:819940388,或關注微信公眾號:Java資訊庫,回覆“架構”,免費的大型網際網路Java視訊分享給大家。
這裡寫圖片描述

相關文章