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.