【算法】找出平衡括号的排列组合
用c#编写一个函数,列出一个字符串列表,此字符串表示平衡n对括号的所有方法的排列组合。
示例:
BalancedParens(0) returns List<string> with element: ""
BalancedParens(1) returns List<string> with element: "()"
BalancedParens(2) returns List<string> with elements: "()()","(())"
BalancedParens(3) returns List<string> with elements: "()()()","(())()","()(())","(()())","((()))"
这个算法使用递归的方法生成所有可能的平衡括号组合:
1. 创建一个空的字符串列表 `result`,用于存储生成的括号组合。
2. 调用 `GenerateParens` 方法,传入初始参数 `result`、空字符串 `""`、括号对数 `n` 和 `n`。
3. 在 `GenerateParens` 方法中进行以下操作:
- 基本情况:如果没有剩余的开括号和闭括号,即 `open` 和 `close` 都等于 0,则将当前字符串 `current` 添加到 `result` 列表中,并返回。
- 如果还有剩余的开括号,即 `open` 大于 0,则将一个开括号添加到 `current` 字符串中,并递归调用 `GenerateParens` 方法,将 `open` 减 1。
- 如果剩余的闭括号数量大于剩余的开括号数量,即 `close` 大于 `open`,则将一个闭括号添加到 `current` 字符串中,并递归调用 `GenerateParens` 方法,将 `close` 减 1。
4. 在 `Main` 方法中进行以下操作:
- 调用 `BalancedParens` 方法,传入括号对数作为参数,获取生成的括号组合列表。
- 使用 `string.Join` 方法将列表中的元素以逗号分隔并打印输出。
using System; using System.Collections.Generic; public class Program { public static List<string> BalancedParens(int n) { List<string> result = new List<string>(); GenerateParens(result, "", n, n); return result; } private static void GenerateParens(List<string> result, string current, int open, int close) { // Base case: All parentheses have been used if (open == 0 && close == 0) { result.Add(current); return; } // If there are still open parentheses remaining, add an opening parenthesis if (open > 0) { GenerateParens(result, current + "(", open - 1, close); } // If there are more closed parentheses than open parentheses, add a closing parenthesis if (close > open) { GenerateParens(result, current + ")", open, close - 1); } } }
测试用例:
TestParens
方法是一个辅助方法,用于生成预期的括号组合列表。它使用了深度优先搜索(DFS)的思想,通过递归地添加开括号和闭括号来生成所有可能的组合。生成的组合被添加到列表 lst
中,并最终返回。
测试用例的设计思路是:根据不同的括号对数,生成预期的括号组合列表,然后调用 BalancedParens
方法生成的括号组合列表,并使用断言来验证两者是否相等。这样,我们可以确保算法在不同输入情况下都能正确生成平衡的括号组合。同时,通过对输入的括号对数进行随机化处理,可以增加测试的覆盖范围,提高测试的可靠性。
using NUnit.Framework; using System; using System.Text; using System.Collections.Generic; public class SolutionTest { [Test] public void TestCases() { var warriorResult = new List<string>(); var testList = new List<string>(); var testValues = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; Shuffle(testValues); foreach (int target in testValues) { testList = TestParens(target); testList.Sort(); warriorResult = Balanced.BalancedParens(target); warriorResult.Sort(); Assert.AreEqual(testList, warriorResult); Console.WriteLine("Value of n = " + target); } } private static void Shuffle<T>(List<T> deck) { var rnd = new Random(); for (int n = deck.Count - 1; n > 0; --n) { int k = rnd.Next(n + 1); T temp = deck[n]; deck[n] = deck[k]; deck[k] = temp; } } private static List<string> TestParens(int n) { var lst = new List<string>(); var sb = new StringBuilder(); Dfs(sb, lst, 0, 0, n); return lst; } private static void Dfs(StringBuilder sb, List<string> lst, int open, int close, int max) { if (close == max) { lst.Add(sb.ToString()); return; } if (open > close) { sb.Append(')'); Dfs(sb, lst, open, close + 1, max); sb.Remove(sb.Length - 1, 1); } if (open < max) { sb.Append('('); Dfs(sb, lst, open + 1, close, max); sb.Remove(sb.Length - 1, 1); } } }