【DFS】括号生成(DFS + 栈)

一、题目

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/generate-parentheses/

二、题解

dfs

题目给出n,那么结果中一定会有n对括号,也就是2 * n个字符,我们只需要枚举这2n个字符的每一位即可,每一位有两种选择:选择 ( 或者 选择 ),我们只需要在递归的出口收集结果即可,决策树如下

对括号序列进行合法性判断:

【栈】有效的括号(括号匹配)---数据结构栈的应用-CSDN博客文章浏览阅读209次。通过栈来解决,遍历串,如果是左括号就入栈,如果是右括号就与栈顶括号对比。https://blog.csdn.net/2202_75999061/article/details/140083306?spm=1001.2014.3001.5502

class Solution {
public:
    vector<string> res;
    string path;
    int n;

    bool islegal(string path) {
        if (path.size() <= 0) return true;
        char stack[n * 2];
        int top = -1;
        for (auto x : path) {
            if (x == '(') stack[++top] = x;
            else {
                if (top < 0) return false;
                else if (x == ')' && stack[top] == '(') top--;
                else return false;
            }
        }
        return top == -1;
    }

    int cnt;

    void dfs(int u) {
        cnt ++;
        if (u == 2 * n) {
            if (islegal(path)) 
                res.push_back(path);
            return;
        }
        path += '(';
        dfs(u + 1);
        path.pop_back();

        path += ')';
        dfs(u + 1);
        path.pop_back();
    }

    vector<string> generateParenthesis(int _n) {
        n = _n;
        return res;
    }
};
小优化

上述dfs过程中,我们发现有在dfs过程中有一些分支是没有必要继续去dfs的,比如 在第一个位置选择时,我们选择右括号,右括号开头他注定不是一个合法的括号序列,所以这个分支我们没必要继续枚举后面不是答案的情况,再比如 ())这种也是无效的括号序列,不难发现在dfs过程中无效的括号序列在除去前面有效部分之后,是以)开头的 ())取出有效括号()后剩余) 剪枝前后dfs次数对比

class Solution {
public:
    vector<string> res;
    string path;
    int n;

    // 判断是否需要进行剪枝
    bool isForget(string path) {
        if (path.size() <= 0) return true;
        char stack[n * 2];
        int top = -1;
        for (auto x : path) {
            if (x == '(') stack[++top] = x;
            else {
                if (top < 0) return false;
                else if (x == ')' && stack[top] == '(') top--;
                else return false;
            }
        }
        return top == -1 || stack[top] == '(' ;
    }

    // 判断序列是否合法
    bool islegal(string path) {
        if (path.size() <= 0) return true;
        char stack[n * 2];
        int top = -1;
        for (auto x : path) {
            if (x == '(') stack[++top] = x;
            else {
                if (top < 0) return false;
                else if (x == ')' && stack[top] == '(') top--;
                else return false;
            }
        }
        return top == -1;
    }

    void dfs(int u) {
        if (u == 2 * n) {  // 递归出口收集答案
            if (islegal(path)) 
                res.push_back(path);
            return;
        }

        if (!isForget(path)) return; // 剪枝

        path += '(';  // 选择 (
        dfs(u + 1);
        path.pop_back();

        path += ')';  // 选择 )
        dfs(u + 1);
        path.pop_back();
    }

    vector<string> generateParenthesis(int _n) {
        n = _n;
        dfs(0);
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值