常见面试题合集

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.   

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

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