返回

从零开始写算法:LeetCode 22 括号生成,解决所有括号排列的难题

后端

算法导读

在算法的世界中,LeetCode 22 括号生成 是一个经典的难题,它要求我们编写一个算法来生成所有可能且符合括号规则的 n 对括号排列。从初学者到资深程序员,这个题目都是一个磨练算法思维的绝佳机会。

在本文中,我们将从头开始理解如何使用递归和回溯法来解决括号生成问题。通过示例和代码演示,我们将掌握核心思路和实现方法,并探索算法解决问题的能力。

问题陈述

给定一个正整数 n,要求设计一个算法输出所有可能且符合括号规则的 n 对括号排列。

例如,当 n = 3 时,所有可能的括号排列如下:

"((()))",
"(()())",
"(())()",
"()(())",
"()()()"

算法思路

为了解决括号生成问题,我们可以使用递归和回溯法。递归是一种分解问题的思想,将原问题分解成若干个规模较小的子问题,然后递归地解决这些子问题。回溯法是一种从可能的解决方案中系统地尝试所有候选解决方案,并在找到不可行的解决方案时回溯到之前的状态。

第一步:递归生成可能的括号序列

  1. 以一个空字符串作为初始状态。
  2. 对于每一个括号对,有两种选择:
    • 将左括号添加到字符串的末尾。
    • 将右括号添加到字符串的末尾。
  3. 如果字符串中左括号的数量大于右括号的数量,则继续步骤 2。
  4. 否则,如果字符串中左括号的数量等于右括号的数量,则该字符串是一个有效的括号排列,将其添加到结果集中。

第二步:回溯到之前的状态

如果字符串中左括号的数量大于右括号的数量,则说明当前的括号排列是不合法的。此时,我们需要回溯到之前的状态,尝试其他可能的括号序列。

代码实现

以下是用 Java 实现的括号生成算法:

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        generate(result, "", n, n);
        return result;
    }

    private void generate(List<String> result, String current, int left, int right) {
        if (left == 0 && right == 0) {
            result.add(current);
            return;
        }

        if (left > 0) {
            generate(result, current + "(", left - 1, right);
        }

        if (right > 0 && left < right) {
            generate(result, current + ")", left, right - 1);
        }
    }
}

算法分析

  • 时间复杂度:算法的时间复杂度为 O(4^n),因为对于每对括号,我们有两种选择:添加左括号或添加右括号。
  • 空间复杂度:算法的空间复杂度为 O(n),因为我们最多需要存储 n 对括号。

结语

通过探索 LeetCode 22 括号生成问题,我们不仅掌握了使用递归和回溯法解决算法问题的方法,还提升了算法思维和解决问题的能力。算法世界中还有许多精彩的难题等待着我们去探索,希望本文能激发您对算法的兴趣和热情。