【算法】剑指 Offer II 085. 生成匹配的括号|22. 括号生成|面试题 08.09. 括号(多语言实现)

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

剑指 Offer II 085. 生成匹配的括号|22. 括号生成|面试题 08.09. 括号

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

样例 1:

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

样例 2:

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

提示:

  • 1 <= n <= 8

分析

  • 首先想到的是全排列排列方式,然后再从中挑选满足括号规则的序列。每个字符只可能是 '(' 或者 ')' 两种选择,所以全排列的数量是 22n 个。真正有效的括号序列远远少于这个量。
  • 是否可以直接去穷举生成有效的括号序列呢?
  • 首先要判断什么样的序列是有效的括号序列?
  • 很显然,首先左右括号字符的数量应该相等。
  • 右括号一定是匹配前面某个左括号。
  • 所以只包含左右括号字符,并且从左往右看,右括号数始终小于等于左括号数,最终左右括号数相等的序列就是合理合法合规的括号序列了。

题解

java

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<>();

        this.dfs(n, ans, new char[n * 2], 0, 0);

        return ans;
    }

    private void dfs(int n, List<String> ans, char[] cs, int left, int right) {
        if (left == n && right == n) {
            ans.add(new String(cs));
            return;
        }

        if (left < n) {
            cs[left + right] = '(';
            dfs(n, ans, cs, left + 1, right);
        }
        if (right < left) {
            cs[left + right] = ')';
            dfs(n, ans, cs, left, right + 1);
        }
    }
}

c

#define MAX_SIZE 1430

void dfs(int n, int *returnSize, char **ans, char *cs, int left, int right) {
    if (left == n && right == n) {
        ans[(*returnSize)] = calloc((n * 2 + 1), sizeof(char));
        strcpy(ans[(*returnSize)], cs);
        ++(*returnSize);
        return;
    }

    if (left < n) {
        cs[left + right] = '(';
        dfs(n, returnSize, ans, cs, left + 1, right);
    }
    if (right < left) {
        cs[left + right] = ')';
        dfs(n, returnSize, ans, cs, left, right + 1);
    }
}

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char **generateParenthesis(int n, int *returnSize) {
    *returnSize = 0;
    char **ans = malloc(MAX_SIZE * sizeof(char *));
    char *cs = calloc((n * 2 + 1), sizeof(char));
    dfs(n, returnSize, ans, cs, 0, 0);
    return ans;
}

c++

class Solution {
private:
    void dfs(int n, vector<string> &ans, string &buf, int left, int right) {
        if (left == n && right == n) {
            ans.push_back(buf);
            return;
        }

        if (left < n) {
            buf.push_back('(');
            dfs(n, ans, buf, left + 1, right);
            buf.pop_back();
        }
        if (right < left) {
            buf.push_back(')');
            dfs(n, ans, buf, left, right + 1);
            buf.pop_back();
        }
    }

public:
    vector<string> generateParenthesis(int n) {
        vector<string> ans;
        string buf;
        dfs(n, ans, buf, 0, 0);
        return ans;
    }
};

python

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans = []

        def dfs(s, left, right):
            if left == n and right == n:
                ans.append(''.join(s))
                return
            if left < n:
                s.append('(')
                dfs(s, left + 1, right)
                s.pop()
            if right < left:
                s.append(')')
                dfs(s, left, right + 1)
                s.pop()

        dfs([], 0, 0)
        return ans
        

go

func generateParenthesis(n int) []string {
    var ans []string

    var dfs func(cs []byte, left int, right int)
    dfs = func(cs []byte, left int, right int) {
        if left == n && right == n {
            ans = append(ans, string(cs))
            return
        }

        if left < n {
            cs[left+right] = '('
            dfs(cs, left+1, right)
        }
        if right < left {
            cs[left+right] = ')'
            dfs(cs, left, right+1)
        }
    }

    dfs(make([]byte, n*2), 0, 0)

    return ans
}

rust

impl Solution {
    pub fn generate_parenthesis(n: i32) -> Vec<String> {
        let mut ans = Vec::new();

        fn dfs(n: usize, ans: &mut Vec<String>, buf: &mut String, left: usize, right: usize) {
            if left == n && right == n {
                ans.push(buf.clone());
                return;
            }
            if left < n {
                buf.push('(');
                dfs(n, ans, buf, left + 1, right);
                buf.pop();
            }
            if right < left {
                buf.push(')');
                dfs(n, ans, buf, left, right + 1);
                buf.pop();
            }
        }

        dfs(n as usize, &mut ans, &mut String::new(), 0, 0);

        ans
    }
}

在这里插入图片描述


原题传送门:https://leetcode-cn.com/problems/IDBivT/

原题传送门:https://leetcode-cn.com/problems/generate-parentheses/

原题传送门:https://leetcode.cn/problems/bracket-lcci/


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://developer.aliyun.com/profile/sqd6avc7qgj7y 博客原创~

相关文章
|
7月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
算法
面试场景题:如何设计一个抢红包随机算法
本文详细解析了抢红包随机算法的设计与实现,涵盖三种解法:随机分配法、二倍均值法和线段切割法。随机分配法通过逐次随机分配金额确保总额不变,但易导致两极分化;二倍均值法优化了金额分布,使每次抢到的金额更均衡;线段切割法则将总金额视为线段,通过随机切割点生成子金额,手气最佳金额可能更高。代码示例清晰,结果对比直观,为面试中类似算法题提供了全面思路。
2028 16
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
655 16
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩分享分库分表的基因算法设计,涵盖分片键选择、水平拆分策略及基因法优化查询效率等内容,助力面试者应对大厂技术面试,提高架构设计能力。
美团面试:百亿级分片,如何设计基因算法?
|
算法 前端开发 Java
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
这篇文章总结了单链表的常见面试题,并提供了详细的问题分析、思路分析以及Java代码实现,包括求单链表中有效节点的个数、查找单链表中的倒数第k个节点、单链表的反转以及从尾到头打印单链表等题目。
231 1
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
424 4
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩在读者群中分享了关于分库分表的基因算法设计,旨在帮助大家应对一线互联网企业的面试题。文章详细介绍了分库分表的背景、分片键的设计目标和建议,以及基因法的具体应用和优缺点。通过系统化的梳理,帮助读者提升架构、设计和开发水平,顺利通过面试。
美团面试:百亿级分片,如何设计基因算法?
|
7月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
673 0
|
7月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
429 2

热门文章

最新文章