【LeetCode22】括号生成(DFS回溯剪枝-多种解法)

举报
野猪佩奇996 发表于 2022/01/23 02:13:50 2022/01/23
【摘要】 文章目录 1.题目2.常规的遍历3.剪枝处理4.根据条件判断是否遍历5.其他写法 1.题目 2.常规的遍历 对于这种要找到所有符合情况的,先明白二叉树是咋样的(树高为2n,因为n为括...

1.题目

在这里插入图片描述

2.常规的遍历

对于这种要找到所有符合情况的,先明白二叉树是咋样的(树高为2n,因为n为括号对数,一对有左右两个括号),再进行剪枝获得满足要求的情况:
在这里插入图片描述
遍历上面二叉树的代码如下:

class Solution {
private:
    vector<string>ans;
public:
    vector<string> generateParenthesis(int n) {
        dfs(n,"");
        return ans;
    }
    void dfs(int n,string path){
        if(path.size()==2*n){//遍历到叶结点
            ans.push_back(path);
            return;
        }
        dfs(n,path+"(");
        dfs(n,path+")");
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

显然上面找出了很多不满足要求的:

["((((((","((((()","(((()(","(((())","((()((","((()()","((())(","((()))","(()(((","(()(()","(()()(","(()())","(())((","(())()","(()))(","(())))","()((((","()((()","()(()(","()(())","()()((","()()()","()())(","()()))","())(((","())(()","())()(","())())","()))((","()))()","())))(","()))))",")(((((",")(((()",")((()(",")((())",")(()((",")(()()",")(())(",")(()))",")()(((",")()(()",")()()(",")()())",")())((",")())()",")()))(",")())))","))((((","))((()","))(()(","))(())","))()((","))()()","))())(","))()))",")))(((",")))(()",")))()(",")))())","))))((","))))()",")))))(","))))))"]

  
 
  • 1

而我们要的是:

["((()))","(()())","(())()","()(())","()()()"]

  
 
  • 1

常规遍历理解后,就是剪枝处理:

3.剪枝处理

(1)右括号close数量大于左括号open时不符合
(2)左括号或者右括号数量大于n时不符合
需要判断左括号数和右括号数,所以递归函数要传参open和close括号数值。
在这里插入图片描述

class Solution {
private:
    vector<string>ans;
public:
    vector<string> generateParenthesis(int n) {
        dfs(n,"",0,0);
        return ans;
    }
    void dfs(int n,string path,int open,int close){
        if(open>n || close>n || close>open){
            return;
        }
        if(path.size()==2*n){//遍历到叶结点
            ans.push_back(path);
            return;
        }
        dfs(n,path+"(",open+1,close);
        dfs(n,path+")",open,close+1);
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

4.根据条件判断是否遍历

进入左子树的资格: open<n
进入右子树的资格:close<open(右括号比左括号多就没法玩了)
上面的判定条件还是要举例画出二叉树判断下才知道。

class Solution {
private:
    vector<string>ans;
public:
    vector<string> generateParenthesis(int n) {
        dfs(n,"",0,0);
        return ans;
    }
    void dfs(int n,string path,int open,int close){
        if(path.size()==2*n){//遍历到叶结点
            ans.push_back(path);
            return;
        }
        if(open<n  && close<=n){
            dfs(n,path+"(",open+1,close);//左子树
        }
        if(close<open && close<=n && open<=n){
            dfs(n,path+")",open,close+1);//右子树
        }
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

5.其他写法

如果path不用上面的写法,可以用push和pop写法(不要漏了pop):

class Solution {
private:
    vector<string>ans;
public:
    vector<string> generateParenthesis(int n) {
        dfs(n,"",0,0);
        return ans;
    }
    void dfs(int n,string path,int open,int close){
        if(path.size()==2*n){//遍历到叶结点
            ans.push_back(path);
            return;
        }
        if(open<n  && close<=n){
            path.push_back('(');
            dfs(n,path,open+1,close);//左子树
            path.pop_back();
        }
        if(close<open && close<=n && open<=n){
            path.push_back(')');
            dfs(n,path,open,close+1);//右子树
            path.pop_back();
        }
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/115624425

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。