自我修炼_中级算法篇_leetcode_第15题

括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

 

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:

输入:n = 1
输出:["()"]
 

提示:

1 <= n <= 8

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/xv33m7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 这道题没有做出来。看到题解的也没有搞懂他怎么能将所有的情况都考虑到。最后一步一步debug发现了奥妙。

首先 左括号的数量一定是等于右括号的数量的

其次 任意位置的左括号的数量一定是大于右括号的数量的

以3为例:

left++递归了3层函数

当进入第三层后会执行right++的操作 也就是我们的左括号3个加入an,然后在进入递归将右括号加入三次这时候因为left = 3 所以不会进入上面的呢半部分。之后将结果((()))放入容器ans中,会huisu函数,将an删除最后一个元素。关键来了一直减到右括号不存在an后,左括号-1后!这时候left是2。再次进入huisu函数这时候,left是3 但是an中只有“((”这时候在会进入下半部分的函数执行加)的操作。这就是这个算法的流程核心。

讲完算法的核心,如何运作我们来看一下如何想到这个算法。

其思想其实是我们很熟悉的深度优先遍历的算法我们按照

1.首先 左括号的数量一定是等于右括号的数量的

2.其次 任意位置的左括号的数量一定是大于右括号的数量的

基于此规则我们来进行深度优先遍历

 基于规则我们将不符合规则的画上红色标记

对于这个算法而言

//伪代码
void dfs(int left,int right,vector<int> a)
{
    //递归出口
    //首先我们第一次加入括号一定要是左括号的 这是第二条原则
    代码部分
    dfs(left+1,right,a+'(');//加入左括号
    dfs(left,right,a+')');加入右括号
}

 因为我们这样就很像一颗二叉树,所以我们可以使用dfs 只用加入递归出口的条件。

class Solution {
public:
    string an;
    void huisu(int left,int right,int n,vector<string>& ans){
        if(an.length() ==n*2){
            ans.push_back(an);
        }
        if(left<n){
            an.push_back('(');
            huisu(left+1,right,n,ans);
            an.pop_back();
        }
        if(right<left){
            an.push_back(')');
            huisu(left,right+1,n,ans);
            an.pop_back();
        }
    }
    vector<string> generateParenthesis(int n) {
        vector<string> ans;
        huisu(0,0,n,ans);
        return ans;
    }
   
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值