【算法】剑指 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 博客原创~

相关文章
|
2月前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
13天前
|
机器学习/深度学习 JavaScript 算法
面试中的网红虚拟DOM,你知多少呢?深入解读diff算法
该文章深入探讨了虚拟DOM的概念及其diff算法,解释了虚拟DOM如何最小化实际DOM的更新,以此提升web应用的性能,并详细分析了diff算法的实现机制。
|
2月前
|
JavaScript 算法 索引
【Vue面试题二十三】、你了解vue的diff算法吗?说说看
这篇文章深入分析了Vue中的diff算法,解释了其在新旧虚拟DOM节点比较中的工作机制,包括同层节点比较、循环向中间收拢的策略,并通过实例演示了diff算法的执行过程,同时提供了源码层面的解析,说明了当数据变化时,如何通过Watcher触发patch函数来更新DOM。
【Vue面试题二十三】、你了解vue的diff算法吗?说说看
|
2月前
|
机器学习/深度学习 算法 数据中心
【机器学习】面试问答:PCA算法介绍?PCA算法过程?PCA为什么要中心化处理?PCA为什么要做正交变化?PCA与线性判别分析LDA降维的区别?
本文介绍了主成分分析(PCA)算法,包括PCA的基本概念、算法过程、中心化处理的必要性、正交变换的目的,以及PCA与线性判别分析(LDA)在降维上的区别。
57 4
|
2月前
|
机器学习/深度学习 算法 数据挖掘
|
2月前
|
算法 C++
第一周算法设计与分析 H : 括号匹配
这篇文章介绍了解决算法问题"括号匹配"的方法,通过使用栈来检查给定字符串中的括号是否合法匹配,并提供了相应的C++代码实现。
|
2月前
|
消息中间件 存储 算法
这些年背过的面试题——实战算法篇
本文是技术人面试系列实战算法篇,面试中关于实战算法都需要了解哪些内容?一文带你详细了解,欢迎收藏!
|
2月前
|
安全 编译器 C++
【剑指offer】2.2编程语言(p22-p25)——面试题1:string赋值运算函数
【剑指offer】2.2编程语言(p22-p25)——面试题1:string赋值运算函数
|
2天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GA遗传优化的GroupCNN分组卷积网络时间序列预测算法matlab仿真
该算法结合了遗传算法(GA)与分组卷积神经网络(GroupCNN),利用GA优化GroupCNN的网络结构和超参数,提升时间序列预测精度与效率。遗传算法通过模拟自然选择过程中的选择、交叉和变异操作寻找最优解;分组卷积则有效减少了计算成本和参数数量。本项目使用MATLAB2022A实现,并提供完整代码及视频教程。注意:展示图含水印,完整程序运行无水印。
|
1天前
|
算法 决策智能
基于禁忌搜索算法的VRP问题求解matlab仿真,带GUI界面,可设置参数
该程序基于禁忌搜索算法求解车辆路径问题(VRP),使用MATLAB2022a版本实现,并带有GUI界面。用户可通过界面设置参数并查看结果。禁忌搜索算法通过迭代改进当前解,并利用记忆机制避免陷入局部最优。程序包含初始化、定义邻域结构、设置禁忌列表等步骤,最终输出最优路径和相关数据图表。