面试题 08.09. 括号

130 篇文章 0 订阅

题目

括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。
说明:解集不能包含重复的子集。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

解题思路

回溯 + 栈

  • 根据题意分析可知
    • 第一个括号是")",一定无法配对成功
    • "(“和”)"的数量一定相同
  • 使用回溯方法,得出所有的排列方式
  • 使用"栈"帮助检查括号是否可以完全配对

代码

class Solution {
  private List<String> list;

  public List<String> generateParenthesis(int n) {
    char[] parentheses = {'(', ')'};
    list = new ArrayList<>();
    backtrack(parentheses, new StringBuilder(), n);
    return list;
  }

  private void backtrack(char[] parentheses, StringBuilder sb, int n) {
    if (sb.length() == n * 2) {
      if (isPair(sb)) list.add(sb.toString());
      return;
    }
    for (char p : parentheses) {
      if (!valid(sb, n)) return;
      sb.append(p);
      backtrack(parentheses, sb, n);
      sb.deleteCharAt(sb.length() - 1);
    }
  }

  /**
   * 检查基本合法性
   *
   * @param sb
   * @param n
   * @return
   */
  private boolean valid(StringBuilder sb, int n) {
    // 如果第一个是")",无法配对
    if (sb.length() > 0 && sb.charAt(0) == ')') return false;
    if (sb.length() <= n) return true;
    int leftNum = 0, rightNum = 0;
    for (int i = 0; i < sb.length(); i++) {
      // 如果"("或")"超过半数,无法配对
      if (leftNum > n || rightNum > n) return false;
      if (sb.charAt(i) == '(') leftNum++;
      else rightNum++;
    }
    return true;
  }

  /**
   * 是否配对
   *
   * @param sb
   * @return
   */
  private boolean isPair(StringBuilder sb) {
    Deque<Character> stack = new LinkedList<>();
    for (int i = 0; i < sb.length(); i++) {
      char c = sb.charAt(i);
      // 如果栈空 或者 栈顶是")" 或者 当前要入栈的是"("的情况下,入栈
      if (stack.isEmpty() || stack.peek() == ')' || c == '(') stack.add(c);
      // 要入栈的是")",栈顶是"(",配对成功,将栈顶"("出栈
      else if (c == ')') stack.pop();
    }
    // 如果都配对成功,栈为空
    return stack.isEmpty();
  }
}

题目来源:力扣(LeetCode)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡矣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值