1. 程式人生 > >【LeetCode】22. Generate Parentheses(C++)

【LeetCode】22. Generate Parentheses(C++)

地址:https://leetcode.com/problems/generate-parentheses/

題目:

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n n = 3, a solution set is:
Example

:
在這裡插入圖片描述

理解:

想到了檢驗是否是有效序列的那道題。
另外,資料結構裡經常出的幾個數字出入棧的所有可能情況也是一樣的。對於有 n n 個數的集合,出入棧情況可以用卡特蘭數(Catalan number)計算:
1 n

+ 1 C 2 n n
\frac{1}{n+1}C_{2n}^{n}

這道題是要生成所有的有效序列。
一個重要的性質:在當前位置,如果右括號的數目大於左括號的數目,則該序列一定是無效的。
由於是從左到右生成,因此在每一個位置保證當前位置有效,然後繼續插入即可。實現有兩種,大同小異,一種傳遞的是剩餘的可用括號數,一種是序列裡已有的括號數。

實現1:

這種實現left和right是剩餘可新增的括號數。

class Solution {
public:
	vector<string> generateParenthesis(int n) {
		vector<string> res;
		generate(n, n, "", res);
		return res;
	}

	void generate(int left, int right, string curr, vector<string>& res) {
		if (left >= 0 && right >= 0) {
			if (left > right)
				return;
			if (left == 0 && right == 0)
				res.push_back(curr);
			else {
				generate(left - 1, right, curr + "(", res);
				generate(left, right - 1, curr + ")", res);
			}
		}
	}
};

實現2(Backtracking)

class Solution {
public:
	vector<string> generateParenthesis(int n) {
		vector<string> res;
		generate(0, 0, n, "", res);
		return res;
	}

	void generate(int left, int right, const int maxLen, string curr, vector<string>& res) {
		if (curr.size() == 2 * maxLen)
			res.push_back(curr);
		else {
			if (left < maxLen)
				generate(left + 1, right, maxLen, curr + "(", res);
			if (right < left)
				generate(left, right + 1, maxLen, curr + ")", res);
		}
	}
};

複雜度分析:
當可以生成有效的序列時,才會產生函式呼叫。
卡特蘭數的上限有人推匯出來是 O ( 4 n n ) O\left(\frac{4^n}{\sqrt{n}}\right)

  • 時間複雜度: O ( 4 n n ) O\left(\frac{4^n}{\sqrt{n}}\right) 。每個有效的序列在backtracking過程中有n步。
  • 空間複雜度: O ( 4 n n ) O\left(\frac{4^n}{\sqrt{n}}\right) ,另外有 O ( n ) O(n) 的空間儲存序列。