1. 程式人生 > 實用技巧 >微軟面試題: LeetCode 2. 括號生成 middle 出現次數:3

微軟面試題: LeetCode 2. 括號生成 middle 出現次數:3

題目描述:

  數字n代表生成括號的對數,請你設計一個函式,用於能夠生成所有可能的並且有效的括號組合。

方法一: 回溯 + 剪枝

將 生成 n 對 有效括號的過程就是在一棵剪枝了的二叉樹上遍歷的過程。下圖是 n = 3 的情況。

  從上面的圖片中我們可以很明顯的看到,最後五條畫黑線的葉節點就是最終的結果,其中左分支都是新增左括號,

右分支都是新增右括號。

新增左(右)括號的條件是 當前還有 左(右)括號可以用,特別地,新增右括號還需要當前 已經新增的右括號的數量

不能比已經新增的左括號的多。因為 合法的括號序列的第一個一定是左括號,此時右括號數量要是比左括號多,那一定有右括號

還沒有左括號配對。

所以,剪枝條件 就是 if (l > n || r > n || r > l) { return } 。l ,r 分別表示當前狀態下,序列中 左右括號的數量。初始化為 0;

如上圖,遍歷到黑線葉節點,即得到 了一個合法的 括號序列,需要將得到的合法序列 放到結果集中。

程式碼如下:

class Solution {
public:
    vector<string> generateParenthesis(int n)
	{
		N = n;
		res.clear();
		dfs("",0,0);
		return res;
    }
	void dfs(string str,int l,int r)
	{
		if(l > N || r > N || r > l)
		{
			return;
		}
		if(l == N && r == N)
		{
			res.push_back(str);
			return;
		}
		dfs(str + '(', l + 1, r);
		dfs(str + ')', l, r + 1);
		return;
	}
private:
	vector<string> res;
	int N;
};

方法二: 動態規劃

分析:動態規劃的問題可以使用類似於數學歸納法的思想來分析,假設我們已經知道了 0,1,2,... ,n-1 對括號的所有的合法括號序列,

現在 求 有 n 對括號的所有的合法序列。對 一個 有 n 對 括號的 合法括號序列,一定是 '(' 開頭的 。

合法括號序列的 形式為 "(" + in_str +")" + out_str ,且in_str 和 out_str 都是合法的括號序列串或空串。

假設 "(" + in_str +")" + out_str 是一個有n 對 括號的 合法括號序列,假設 in_str 有 n1 對括號,out_str 有n2 對括號。

n 1 和 n2 之間必須滿足:

0 <= n1 <= n-1 ,0 <= n2 <= n-1 , n1 + n2 = n - 1

假設 n = 3 ,則有

n1 n2

0 2

1 1

2 0

所以,求有n 對 括號的所有的合法括號序列,即求上面 n_str 和 out_str 的所有組合情況。

另 vector<vector<string>>dp(n+1); dp[i] 表示有i 對 括號的 所有合法序列,設 0<= j <= i-1 ,則 in_str 是 dp[ j ]中的一個序列,

同時 out_str 是 dp[i-1 -j] 中的一個序列。

c++ 程式碼如下:

 1 class Solution {
 2 public:
 3     vector<string> generateParenthesis(int n) {
 4         vector<vector<string> > dp(n+1);
 5         if( n <= 0)     return {};
 6         //base case
 7         dp[0] = {""};
 8         dp[1] = {"()"};
 9         //dp status move
10         for(int i = 2; i <= n;++i)
11         {
12             for(int j = 0;j <= i-1 ; ++j)
13             {
14                 for(string &in_str:dp[j])
15                    for(string &out_str:dp[i-1-j])
16                    {
17                        string str_tmp = "(" + in_str + ")" + out_str;
18                        dp[i].push_back(str_tmp);
19                    }
20             }
21         }
22         return dp[n];
23     }
24 };