【LeetCode 22 回溯算法专项】括号生成

文章目录

    • 1. 题目
      • 1.1 示例
      • 1.2 说明
      • 1.3 限制
    • 2. 解法一
      • 2.1 分析
      • 2.2 解答

1. 题目

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

1.1 示例

  • 示例 1 1 1

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

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

1.2 说明

  • 来源: 力扣(LeetCode)
  • 链接: https://leetcode-cn.com/problems/generate-parentheses/

1.3 限制

  • 1 <= n <= 8

2. 解法一

2.1 分析

实际上,需要首先说明的是,题目这里使用组合这个用词是不准确的,因为组合是没有顺序可言的,于是一组括号组合也就没有合法性可言。这里应该将括号组合改为括号排列比较合适。

因此,上述题目该成这样的表述比较合适:

现在有 2 n 2n 2n 个位置,每个位置可以放置字符 ( 或者 ) ,组成的所有括号排列中,有多少个是合法的?

  • 作者: 回溯算法最佳实践:合法括号生成

有关括号问题,你只要记住两个个性质,思路就很容易想出来:

  1. 一个「合法」括号排列的左括号数量一定等于右括号数量,这个显而易见
  2. 对于一个「合法」的括号字符串排列 p ,必然对于任何 0 <= i <= len(p) 都有:子串 p[0:i] (Python 切片操作左闭右开)中左括号的数量都大于或等于右括号的数量

以上两点是一个括号字符串是否为合法字符串排列的一组充分必要条件。仿照全排列的原理再加上下列递归出口条件即可:

2.2 解答

from typing import List


class Solution:
    def __init__(self):
        self.parentheses = []

    def _backtrack(self, left: int, right: int, track: List[str]):
        if left > right:  # 若左括号剩下的多,说明不合法
            return
        if left < 0 or right < 0:  # 括号剩余数量小于 0 肯定是不合法的
            return
        if left == 0 and right == 0:  # 当所有括号都恰好用完时,得到一个合法的括号组合
            self.parentheses.append(''.join(track))
            return

        # 尝试放一个左括号
        track.append('(')  # 选择
        self._backtrack(left - 1, right, track)
        track.pop()  # 撤消选择

        # 尝试放一个右括号
        track.append(')')  # 选择
        self._backtrack(left, right - 1, track)
        track.pop()  # 撤消选择

    def generate_parenthesis(self, n: int) -> List[str]:
        track = []
        self._backtrack(n, n, track)
        return self.parentheses


def main():
    sln = Solution()
    print(sln.generate_parenthesis(3))  # ['((()))', '(()())', '(())()', '()(())', '()()()']


if __name__ == '__main__':
    main()

你可能感兴趣的:(LeetCode,leetcode,算法)