题目描述
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n =_ _3,生成结果为:
["((()))","(()())","(())()","()(())","()()()"]
题解
暴力法
参考自官方。
暴力法的难点在于判断暴力生成的序列组合是否有效。其实方法很简单,从左往右统计左括号和右括号的数量,只要左括号数量一直大于等于右括号数量,并最终左括号数量等于右括号数量即可。
private static bool Valid(char[] current){var balance = 0;foreach (var c in current){if (c == '(') balance++;else balance--;if (balance < 0) return false;}return balance == 0;}
暴力法完整代码:
public static IList<string> GenerateParenthesis(int n){var combinations = new List<string>();GenerateAll(new char[2 * n], 0, combinations);return combinations;}private static void GenerateAll(char[] current, int pos, List<string> res){if (pos == current.Length){if (IsValid(current)) res.Add(new string(current));}else{current[pos] = '(';GenerateAll(current, pos + 1, res);current[pos] = ')';GenerateAll(current, pos + 1, res);}}private static bool IsValid(char[] current){var balance = 0;foreach (var c in current){if (c == '(') balance++;else balance--;if (balance < 0) return false;}return balance == 0;}
回溯法
大体思路和暴力法类似,只是仅在序列依然有效时才添加 ‘(‘ 或 ‘)’。
只要左括号数量小于 n,就能拼接一个左括号
只要右括号数量小于左括号数量,就能拼接一个右括号
public static IList<string> GenerateParenthesis(int n){var res = new List<string>();Backtrack(res, "", 0, 0, n);return res;}private static void Backtrack(ICollection<string> res, string current, int open, int close, int max){if (current.Length == 2 * max){res.Add(current);return;}if (open < max) Backtrack(res, current + "(", open + 1, close, max);if (close < open) Backtrack(res, current + ")", open, close + 1, max);}
