Cover image for 面试经典150题 P22 括号生成

面试经典150题 P22 括号生成


时间轴

时间轴

2025-11-30

init


题目:

暴力回溯方法,最后去重

123456789101112131415161718192021222324252627282930313233343536
#include <vector>#include <string>#include <algorithm>using std::string;using std::vector;#define PARENTHESE "()"class Solution {    private:	void backtrace(string &track, vector<string> &res, int n)	{		if (track.size() == n * 2) {			res.push_back(track);			return;		}		int i, len = track.size();		for (i = 0; i < len; i++) {			track.insert(i, PARENTHESE);			backtrace(track, res, n);			track.erase(i, 2);		}	}    public:	vector<string> generateParenthesis(int n)	{		vector<string> res;		string track(PARENTHESE);		backtrace(track, res, n);		std::sort(res.begin(), res.end());		res.erase(std::unique(res.begin(), res.end()), res.end());		return res;	}};

上面这种方法性能较低,原因是我们生成了大量重复的结果,最后还要过滤重复的。

另外一种方法:考虑下面所述:

如果左括号数量不大于 n,我们可以放一个左括号。如果右括号数量小于左括号的数量,我们可以放一个右括号。

搜索树如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243
"" (3,3)├─ "(" (2,3)│  ││  ├─ "((" (1,3)│  │  ││  │  ├─ "(((" (0,3)│  │  │  ││  │  │  └─ "((()" (0,2)│  │  │      ││  │  │      └─ "((())" (0,1)│  │  │          ││  │  │          └─ "((()))" (0,0) ✅│  │  ││  │  └─ "(()" (1,2)│  │      ││  │      ├─ "(()(" (0,2)│  │      │  ││  │      │  └─ "(()()" (0,1)│  │      │      ││  │      │      └─ "(()())" (0,0) ✅│  │      ││  │      └─ "(())" (1,1)│  │          ││  │          └─ "(())(" (0,1)│  │              ││  │              └─ "(())()" (0,0) ✅│  ││  └─ "()" (2,2)│      ││      └─ "()(" (1,2)│          ││          ├─ "()((" (0,2)│          │  ││          │  └─ "()(()" (0,1)│          │      ││          │      └─ "()(())" (0,0) ✅│          ││          └─ "()()" (1,1)│              ││              └─ "()()(" (0,1)│                  ││                  └─ "()()()" (0,0) ✅

代码如下:

12345678910111213141516171819202122232425262728293031323334353637
#include <vector>#include <string>using std::string;using std::vector;class Solution {    private:	void backtrace(string &track, vector<string> &res, int left, int right)	{		if (left == 0 && right == 0) {			return res.push_back(track);		}		if (left > 0) {			track.push_back('(');			backtrace(track, res, left - 1, right);			track.pop_back();		}		if (right > left) { // right must be more than left			track.push_back(')');			backtrace(track, res, left, right - 1);			track.pop_back();		}	}    public:	vector<string> generateParenthesis(int n)	{		vector<string> res;		string track;		backtrace(track, res, n, n);		return res;	}};

leetcode hot 100 rewrite, 并没有想到剪枝的方法:

123456789101112131415161718192021222324252627282930313233343536373839404142434445
#include <vector>#include <string>#include <algorithm>using std::vector;using std::string;class Solution {    private:        void __generateParentesis(vector<string> &res, string &curr, int nr_par, int pos)        {                if (curr.size() == 2 * nr_par) {                        res.push_back(curr);                        return;                }                int i, n = curr.size();                for (i = pos; i < n; i++) {                        curr.insert(i, "()");                        __generateParentesis(res, curr, nr_par, pos + 1);                        curr.erase(i, 2);                }        }    public:        vector<string> generateParenthesis(int n)        {                // 1 <= n <= 8                vector<string> res;                string curr = "()";                if (n == 1) {                        res.push_back(curr);                        return res;                }                __generateParentesis(res, curr, n, 0);                std::sort(res.begin(), res.end());                res.erase(std::unique(res.begin(), res.end()), res.end());                return res;        }};
评论加载中…