1. 程式人生 > >資料結構與演算法面試題80道

資料結構與演算法面試題80道

40.百度研發筆試題 引用自:zp155334877 1)設計一個棧結構,滿足一下條件:min,push,pop操作的時間複雜度為O(1)。 2)一串首尾相連的珠子(m個),有N種顏色(N<=10), 設計一個演算法,取出其中一段,要求包含所有N中顏色,並使長度最短。 並分析時間複雜度與空間複雜度。 3)設計一個系統處理詞語搭配問題,比如說 中國 和人民可以搭配, 則中國人民 人民中國都有效。要求:  *系統每秒的查詢數量可能上千次;  *詞語的數量級為10W;  *每個詞至多可以與1W個詞搭配 當用戶輸入中國人民的時候,要求返回與這個搭配片語相關的資訊。 41.求固晶機的晶元查詢程式 晶元盤由數目不詳的大小一樣的晶元組成,晶元並不一定全佈滿晶元盤, 照相機每次這能匹配一個晶元,如匹配過,則拾取該晶元, 若匹配不過,照相機則按測好的晶元間距移到下一個位置。 求遍歷晶元盤的演算法 求思路。 42.請修改append函式,利用這個函式實現: 兩個非降序連結串列的並集,1->2->3 和 2->3->5 併為 1->2->3->5 另外只能輸出結果,不能修改兩個連結串列的資料。 43.遞迴和非遞迴倆種方法實現二叉樹的前序遍歷。 44.騰訊面試題: 1.設計一個魔方(六面)的程式。 2.有一千萬條簡訊,有重複,以文字檔案的形式儲存,一行一條,有重複。 請用5分鐘時間,找出重複出現最多的前10條。 3.收藏了1萬條url,現在給你一條url,如何找出相似的url。(面試官不解釋何為相似) 45.雅虎: 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 46.搜狐: 四對括號可以有多少種匹配排列方式?比如兩對括號可以有兩種:()()和(()) 47.創新工場: 求一個數組的最長遞減子序列 比如{9,4,3,2,5,4,3,2}的最長遞減子序列為{9,5,4,3,2} 48.微軟: 一個數組是由一個遞減數列左移若干位形成的,比如{4,3,2,1,6,5} 是由{6,5,4,3,2,1}左移兩位形成的,在這種陣列中查詢某一個數。 49.一道看上去很嚇人的演算法面試題: 如何對n個數進行排序,要求時間複雜度O(n),空間複雜度O(1) 50.網易有道筆試: 1.求一個二叉樹中任意兩個節點間的最大距離,兩個節點的距離的定義是 這兩個節點間邊的個數, 比如某個孩子節點和父節點間的距離是1,和相鄰兄弟節點間的距離是2,優化時間空間複雜度。 2.求一個有向連通圖的割點,割點的定義是, 如果除去此節點和與其相關的邊,有向圖不再連通,描述演算法。 ------------------------------------------------------------------- 51.和為n連續正數序列。 題目:輸入一個正數n,輸出所有和為n連續正數序列。 例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以輸出3個連續序列1-5、4-6和7-8。 分析:這是網易的一道面試題。 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; // left child of node       SBinaryTreeNode *m_pRight; // right child of node }; 分析:這道題本質上還是考查二元樹的遍歷。 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; }; 請實現其賦值運算子的過載函式,要求異常安全,即當對一個物件進行賦值時發生異常,物件的狀態不能改變。 56.最長公共字串。 題目:如果字串一的所有字元按其在字串中的順序出現在另外一個字串二中, 則字串一稱之為字串二的子串。 注意,並不要求子串(字串一)的字元必須連續出現在字串二中。 請編寫一個函式,輸入兩個字串,求它們的最長公共子串,並打印出最長公共子串。 例如:輸入兩個字串BDCABA和ABCBDAB,字串BCBA和BDAB都是是它們的最長公共子串, 則輸出它們的長度4,並列印任意一個子串。 分析:求最長公共子串(Longest Common Subsequence, LCS)是一道非常經典的動態規劃題, 因此一些重視演算法的公司像MicroStrategy都把它當作面試題。 57.用倆個棧實現佇列。 題目:某佇列的宣告如下: template<typename T> class CQueue { public:       CQueue() {}       ~CQueue() {}       void appendTail(const T& node); // append a element to tail       void deleteHead();               // remove a element from head private:      T> m_stack1;      T> m_stack2; }; 分析:從上面的類的宣告中,我們發現在佇列中有兩個棧。 因此這道題實質上是要求我們用兩個棧來實現一個佇列。 相信大家對棧和佇列的基本性質都非常瞭解了:棧是一種後入先出的資料容器, 因此對佇列進行的插入和刪除操作都是在棧頂上進行;佇列是一種先入先出的資料容器, 我們總是把新元素插入到佇列的尾部,而從佇列的頭部刪除元素。 58.從尾到頭輸出連結串列。 題目:輸入一個連結串列的頭結點,從尾到頭反過來輸出每個結點的值。連結串列結點定義如下: struct ListNode {       int       m_nKey;       ListNode* m_pNext; }; 分析:這是一道很有意思的面試題。 該題以及它的變體經常出現在各大公司的面試、筆試題中。 59.不能被繼承的類。 題目:用C++設計一個不能被繼承的類。 分析:這是Adobe公司2007年校園招聘的最新筆試題。 這道題除了考察應聘者的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)。 分析:這是一道很新穎的關於位運算的面試題。 62.找出連結串列的第一個公共結點。 題目:兩個單向連結串列,找出它們的第一個公共結點。 連結串列的結點定義為: struct ListNode {       int         m_nKey;       ListNode*   m_pNext; }; 分析:這是一道微軟的面試題。微軟非常喜歡與連結串列相關的題目, 因此在微軟的面試題中,連結串列出現的概率相當高。 63.在字串中刪除特定的字元。 題目:輸入兩個字串,從第一字串中刪除第二個字串中所有的字元。例如,輸入”They are students.”和”aeiou”, 則刪除之後的第一個字串變成”Thy r stdnts.”。 分析:這是一道微軟面試題。在微軟的常見面試題中,與字串相關的題目佔了很大的一部分, 因為寫程式操作字串能很好的反映我們的程式設計基本功。 64. 尋找醜數。 題目:我們把只包含因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數, 但14不是,因為它包含因子7。習慣上我們把1當做是第一個醜數。 求按從小到大的順序的第1500個醜數。 分析:這是一道在網路上廣為流傳的面試題,據說google曾經採用過這道題。 65.輸出1到最大的N位數 題目:輸入數字n,按順序輸出從1最大的n位10進位制數。比如輸入3, 則輸出1、2、3一直到最大的3位數即999。 分析:這是一道很有意思的題目。看起來很簡單,其實裡面卻有不少的玄機。 66.顛倒棧。 題目:用遞迴顛倒一個棧。例如輸入棧{1, 2, 3, 4, 5},1在棧頂。 顛倒之後的棧為{5, 4, 3, 2, 1},5處在棧頂。 67.倆個閒玩娛樂。 1.撲克牌的順子 從撲克牌中隨機抽5張牌,判斷是不是一個順子,即這5張牌是不是連續的。 2-10為數字本身,A為1,J為11,Q為12,K為13,而大小王可以看成任意數字。 2.n個骰子的點數。 把n個骰子扔在地上,所有骰子朝上一面的點數之和為S。輸入n, 打印出S的所有可能的值出現的概率。 68.把陣列排成最小的數。 題目:輸入一個正整數陣列,將它們連線起來排成一個數,輸出能排出的所有數字中最小的一個。 例如輸入陣列{32, 321},則輸出這兩個能排成的最小數字32132。 請給出解決問題的演算法,並證明該演算法。 分析:這是09年6月份百度的一道面試題, 從這道題我們可以看出百度對應聘者在演算法方面有很高的要求。 69.旋轉陣列中的最小元素。 題目:把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個排好序的陣列的一個旋轉, 輸出旋轉陣列的最小元素。例如陣列{3, 4, 5, 1, 2}為{1, 2, 3, 4, 5}的一個旋轉,該陣列的最小值為1。     分析:這道題最直觀的解法並不難。從頭到尾遍歷陣列一次,就能找出最小的元素, 時間複雜度顯然是O(N)。但這個思路沒有利用輸入陣列的特性,我們應該能找到更好的解法。 70.給出一個函式來輸出一個字串的所有排列。 ANSWER 簡單的回溯就可以實現了。當然排列的產生也有很多種演算法,去看看組合數學, 還有逆序生成排列和一些不需要遞迴生成排列的方法。 印象中Knuth的<TAOCP>第一卷裡面深入講了排列的生成。這些演算法的理解需要一定的數學功底, 也需要一定的靈感,有興趣最好看看。 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; } 72. 題目:設計一個類,我們只能生成該類的一個例項。 分析:只能生成一個例項的類是實現了Singleton模式的型別。 73.對策字串的最大長度。 題目:輸入一個字串,輸出該字串中對稱的子字串的最大長度。 比如輸入字串“google”,由於該字串裡最長的對稱子字串是“goog”,因此輸出4。 分析:可能很多人都寫過判斷一個字串是不是對稱的函式,這個題目可以看成是該函式的加強版。 74.陣列中超過出現次數超過一半的數字 題目:陣列中有一個數字出現的次數超過了陣列長度的一半,找出這個數字。 分析:這是一道廣為流傳的面試題,包括百度、微軟和Google在內的多家公司都 曾經採用過這個題目。要幾十分鐘的時間裡很好地解答這道題, 除了較好的程式設計能力之外,還需要較快的反應和較強的邏輯思維能力。 75.二叉樹兩個結點的最低共同父結點 題目:二叉樹的結點定義如下: struct TreeNode {     int m_nvalue;     TreeNode* m_pLeft;     TreeNode* m_pRight; }; 輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。 分析:求數中兩個結點的最低共同結點是面試中經常出現的一個問題。這個問題至少有兩個變種。 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),以複製一個複雜連結串列。 分析:在常見的資料結構上稍加變化,這是一種很新穎的面試題。 要在不到一個小時的時間裡解決這種型別的題目,我們需要較快的反應能力, 對資料結構透徹的理解以及紮實的程式設計功底。 77.關於連結串列問題的面試題目如下: 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中。 78.連結串列和陣列的區別在哪裡? 分析:主要在基本概念上的理解。 但是最好能考慮的全面一點,現在公司招人的競爭可能就在細節上產生, 誰比較仔細,誰獲勝的機會就大。 79. 1.編寫實現連結串列排序的一種演算法。說明為什麼你會選擇用這樣的方法? 2.編寫實現陣列排序的一種演算法。說明為什麼你會選擇用這樣的方法? 3.請編寫能直接實現strstr()函式功能的程式碼。 80.阿里巴巴一道筆試題 問題描述: 12個高矮不同的人,排成兩排,每排必須是從矮到高排列,而且第二排比對應的第一排的人高,問排列方式有多少種? 這個筆試題,很YD,因為把某個遞迴關係隱藏得很深。