【LeetCode从零单刷】Generate Parentheses

【非常抱歉,第三层最下面两个节点画反了……】

题目:

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

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

"((()))", "(()())", "(())()", "()(())", "()()()"

解答:

回溯法(剪枝法)。不过虽然原理,写出来却是麻烦。还是要怪自己本科练习不够。先举一个 n=2 的例子:


一般的递归方法,总是要在从底层开始逐个向上层 return一个结果,否则所做的操作没有记录。但是回溯法如果只找到一个结果就 return,却是错误的。所以开始我的代码是这样的:

class Solution {
public:
    set<string> tmp;
    string gao(int left, int right, string it)
    {
        if(left == 0 && right == 0) { return it; }
        
        string ret;
        if(left == right) { tmp.insert(gao(left - 1, right, it + "(")); }
        else {
            if(left > 0) { tmp.insert(gao(left - 1, right, it + "(")); }
            tmp.insert(gao(left, right - 1, it + ")"));
        }
    }
    vector<string> generateParenthesis(int n) {
        gao(n, n, string(""));
        vector<string> ans(tmp.begin(), tmp.end());
        return ans;
    }
};
我还看了好久,很简单的一个错误:除了最底层向上 return 了一次。其他层都无法 return.

那怎么办?其他层总要 return 一点东西啊。但是,如果要return一个可行解的话,让我们看图,因为最底层(第4层)返回了一个结果,在第三层它的父亲处被存入一次,而且在第二层它的祖父处又被存入一次,其实是重复了……幸好set 是避免重复元素存在的。AC代码如下:

这里还用了一个小技巧,利用迭代器 set 转 vector 的构造函数:

vector<Type> test (_set.begin(), _set.end())

class Solution {
public:
    set<string> tmp;
    string gao(int left, int right, string it)
    {
        if(left == 0 && right == 0) { return it; }
        
        string ret;
        if(left == right) { ret = gao(left - 1, right, it + "("); tmp.insert(ret); }
        else {
            if(left > 0) { ret = gao(left - 1, right, it + "("); tmp.insert(ret); }
            ret = gao(left, right - 1, it + ")"); tmp.insert(ret);
        }
        return ret;
    }
    vector<string> generateParenthesis(int n) {
        gao(n, n, string(""));
        vector<string> ans(tmp.begin(), tmp.end());
        return ans;
    }
};

现在想想自己当初真是够蠢……正确的回溯法应该这样的:

  1. 每次只递归一步,绝不多一步。这个和递归法是相同的道理;
  2. 只有最底层负责存入结果,存入一个脱离于函数的全局内存
  3. 层与层之间,不再传递数据(因为回溯的答案不止一个,每层处理去重没必要,交给最底层存入)。但是每层必须有 return 返回上层,否则函数无法终止),return 一个空值
class Solution {
public:
    vector<string> ans;
    void gao(int left, int right, string it)
    {
        if(left == 0 && right == 0) { ans.push_back(it); return; }
        
        if(left == right) { gao(left - 1, right, it + "("); }
        else {
            if(left > 0)  { gao(left - 1, right, it + "("); }
            gao(left, right - 1, it + ")");
        }
        return;<span style="white-space:pre">	</span>// important
    }
    vector<string> generateParenthesis(int n) {
        gao(n, n, string(""));
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值