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.