常見面試題合集

1. N對括號的所有合法排列

題目:給定N對括號,輸出其所有的合法的組合狀態,例如,N=3,所有的合法狀態爲:"((()))”, “(()())”, “(())()”, “()(())”, “()()()”

解法1, DFS:

在每個indx位置,分別進行擴展( 放入左括號 、 放入右括號),並且依據擴展的條件決定是否擴展。

Python代碼:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def dfs_bracket(N, stack, left, right ):
    if left + right == 2*N:  #  left == N and right == N
        print( stack )
        return
    indx = left + right
    # 在每個indx位置擴展 左括號和右括號,配合剪枝
    # 擴展左括號
    if left < N:
        stack[indx] = '('
        dfs_bracket(N, stack, left+1, right )
    # 擴展右括號
    if right < left:
        stack[indx] = ')'
        dfs_bracket(N, stack, left, right+1 )

if __name__ == "__main__":
    N = 3
    l = [None] * 2*N
    dfs_bracket( N, l, 0, 0 )

運行結果:


2. 最長迴文子串

題目:寫一個函數,返回一個字符串中最長迴文字串的長度。

算法一:O(n^3),枚舉每一個子串判定是否爲迴文。

算法二:利用迴文性質。假定所有迴文都有奇數個字符。

       思路:掃描每個索引 i = 1:N,確定以索引 i 爲中心的s1和s2的最長長度爲 P[i] , 則索引 p[i] 爲中心點的迴文最長長度爲  2 * p[i] + 1。 

                   在搜索過程中,利用迴文對稱的性質,減少搜索次數。

      減少搜索次數原理:

                   設 [id_begin  j_begin  j  j_end  id   i_begin  i  i_end  id_end] 中, *_begin 和 *_end 均爲迴文串, *代表中心點,  且 i和j 關於 id對稱。

                   則:[j_begin ... j_end] == [i_begin ... i_end], 故在取得 p[j] 和 p[id] 之後,p[i] 的搜索可以從 i_end開始搜索。

故 p[ i ] 的最小值爲:

if( mx > i )
    p[i] = MIN( p[2*id-i], mx-i );

else

     p[i] = 1;

參考代碼:

void pk()
{
    int i;
    int mx = 0;
    int id;
    for(i=1; i<n; i++)
    {
        if( mx > i )
            p[i] = MIN( p[2*id-i], mx-i );        
        else
            p[i] = 1;
        for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
            ;
        if( p[i] + i > mx )
        {
            mx = p[i] + i;
            id = i;
        }
    }
}

完整的Python 代碼:

 算法3:後綴樹

 

 3. 兄弟單詞

方案一:使用數據結構 map<key,list>。兄弟單詞共用一個簽名key,key爲單詞內部排序後的詞條,list存儲同一key的單詞集合;相對於編程珠璣中的方法,該方法在空間上節省了每個單詞一個key的空間;在時間上,不再需要二分查找,O(1)的查找;但是這種方法還可以優化,見方案二

方案二:使用trie樹。trie樹又稱字典樹,在面試題中關於“字符串”與“數字串”類型的問題中高頻出現,非常實用。對於兄弟單詞,兄弟單詞公用一個key自不必說,只是trie的節點結構應該多出一個域list,用來存儲key對應的兄弟單詞;具體節點結構應該爲

 
 
bool isStr, Node* next[26], vector<const char*> brothers

該方案查詢的複雜度爲O(L),L爲key的平均長度;空間上則有很大的優化,例如單詞的key有“abc”、“abcd”、“abcde”之類的形式,則這些key也能達到空間公用,不過數據量大還好,數據量小,trie樹開闢的空間還是有些浪費。

 4. 字符串組成

題意:就是給定三個字符串A,B,C;判斷C能否由AB中的字符組成,同時這個組合後的字符順序必須是A,B中原來的順序,不能逆序;例如:A:mnl,B:xyz;如果C爲mnxylz,就符合題意;如果C爲mxnzly,就不符合題意,原因是z與y順序不是B中順序。

DP求解:定義dp[i][j]表示A中前i個字符與B中前j個字符是否能組成C中的前 (i+j) 個字符,如果能標記true,如果不能標記false;

強大的DFS: A[i], B[j], C[indx], 則  dfs( i, j, indx ) = {  dfs(i+1, j, indx+1) 或 dfs(i, j+1, indx+1) 或 dfs(i+1, j, indx) 或 dfs(i, j+1, indx)

  5. 逆序對

 

 

 7.   

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

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