若是给出一个正整数,表示一共有多少对括号,如何输出全部括号可能的组合?java
好比:给出的括号对数为3, 则全部括号的组合有以下几种:函数
()()() ()(()) (())() (()()) ((()))
为了解决这个问题,本文采用两种方式来完成。测试
接下来,咱们一块儿来看看广度优先搜索和深度优先搜索的思想和具体实现。spa
所谓广度优先搜索的方式就是尽量早的先输出完整的括号对(), 也就是当输出一个左括号 '(' , 尽量先输出一个右括号 ‘)’ 。code
好比要输出括号对数是2对的全部可能,先输出的结果是()(), 而不是(())。orm
()() (())
咱们能够定义三个值来完成递归调用:递归
currParentheses 当前存放的括号组合状况 leftCount 剩余左括号数 rightCount 剩余右括号数
何时输出一个候选结果?io
当剩余左括号数和剩余右括号数都为0的时候。form
左括号'('和右括号'')输出的时机?class
广度优先搜索的目的是先获得完整的括号对(), 这种状况下须要须要考虑以下两种状况:
有了上述的思想,咱们能够很容易写出相应的程序来。具体代码以下:
/** * 广度优先搜索递归函数 * @param currParentheses 当前存放的括号组合状况 * @param leftCount 剩余左括号数 * @param rightCount 剩余右括号数 */ private void bfsRecu(String currParentheses, int leftCount, int rightCount) { /** * 结束条件: * 当剩余括号数和剩余右括号数都为0时,表示括号已经用完,直接输出就能够打印出一种状况 */ if (leftCount == 0 && rightCount == 0) { System.out.println(currParentheses); } /** * 广度优先搜索的目的是先获得完整的括号对(), 这种状况下 * 须要检查剩余的右括号数是否大于剩余的左括号数,若是大于则表示已经有一个左括号输出了, * 在这种状况下,将当前存放的括号组合状况添加一个右括号,而后右边括号数减1,而后递归调用 * */ if (rightCount > leftCount) { bfsRecu(currParentheses + ')', leftCount, rightCount - 1); } /** * 若是还有剩余左括号数,则将当前存放的括号组合状况添加一个左括号,而后剩余左边括号数减1,而后递归调用便可 */ if (leftCount > 0) { bfsRecu(currParentheses + '(', leftCount - 1, rightCount); } }
有了广度优先搜索的递归调用函数,广度优先搜索方法就能够调用递归函数便可。当前存放括号内容的变量为空。
/** * 广度搜索方式打印括号组合数字 * @param parentheseCount 括号对数 */ public void bfs(int parentheseCount) { if (parentheseCount < 1) { throw new IllegalArgumentException("括号对数不能小于1"); } bfsRecu("", parentheseCount, parentheseCount); }
深度优先搜索的思路和广度优先搜索相似,惟一的区别就是先输出完整的括号对,仍是先尽量多地输出左括号。
广度优先搜索的方式就是尽量早的先输出完整的括号对(), 也就是当输出一个左括号 '(' , 尽量先输出一个右括号 ‘)’ 。
深度优先搜索的方式就是尽量早的先输出左括号('', 也就是若是剩余左括号数大于0的时,先获取左边括号'('。
好比要输出括号对数是2对的全部可能,先输出的结果是(()), 而不是()()。
(()) ()()
和广度优先搜索同样,咱们依旧能够定义三个值来完成递归调用:
currParentheses 当前存放的括号组合状况 leftCount 剩余左括号数 rightCount 剩余右括号数
何时输出一个候选结果?
当剩余左括号数和剩余右括号数都为0的时候。
左括号'('和右括号'')输出的时机?
深度优先搜索的目的是先尽量多的获得左括号'(', 这种状况下须要须要考虑以下两种状况:
有了上述的思想,咱们能够很容易写出相应的程序来。具体代码以下:
/** * 深度优先搜索递归方法 * @param currParentheses 当前存放的括号组合状况 * @param leftCount 剩余左括号数 * @param rightCount 剩余右括号数 */ private void dfsRecu(String currParentheses, int leftCount, int rightCount) { /** * 结束条件: * 当剩余括号数和剩余右括号数都为0时,表示括号已经用完,直接输出就能够打印出一种状况 */ if (leftCount == 0 && rightCount == 0) { System.out.println(currParentheses); } /** * 深度优先搜索的目的是尽量先获取左边括号, 这种状况下, 若是剩余左括号数大于0,则 * 将当前存放的括号组合状况添加一个左括号,而后剩余左边括号数减1,而后递归调用 * */ if (leftCount > 0) { dfsRecu(currParentheses + '(', leftCount - 1, rightCount); } /** * 检查剩余的右括号数是否大于剩余的左括号数,若是大于, * 则将当前存放的括号组合状况添加一个右括号,而后右边括号数减1,而后递归调用 * */ if (rightCount > leftCount) { dfsRecu(currParentheses + ')', leftCount, rightCount - 1); } }
有了深度优先搜索的递归调用函数,深度优先搜索方法就能够调用递归函数便可。
/** * 深度搜索方式打印括号组合数字 * @param parentheseCount 括号对数 */ public void dfs(int parentheseCount) { if (parentheseCount < 1) { throw new IllegalArgumentException("括号对数不能小于1"); } dfsRecu("", parentheseCount, parentheseCount); }
/** * @author wangmengjun */ public class ParenthesesPrinter { /** * 广度搜索方式打印括号组合数字 * @param parentheseCount 括号对数 */ public void bfs(int parentheseCount) { if (parentheseCount < 1) { throw new IllegalArgumentException("括号对数不能小于1"); } bfsRecu("", parentheseCount, parentheseCount); } /** * 广度优先搜索递归函数 * @param currParentheses 当前存放的括号组合状况 * @param leftCount 剩余左括号数 * @param rightCount 剩余右括号数 */ private void bfsRecu(String currParentheses, int leftCount, int rightCount) { /** * 结束条件: * 当剩余括号数和剩余右括号数都为0时,表示括号已经用完,直接输出就能够打印出一种状况 */ if (leftCount == 0 && rightCount == 0) { System.out.println(currParentheses); } /** * 广度优先搜索的目的是先获得完整的括号对(), 这种状况下 * 须要检查剩余的右括号数是否大于剩余的左括号数,若是大于则表示已经有一个左括号输出了, * 在这种状况下,将当前存放的括号组合状况添加一个右括号,而后右边括号数减1,而后递归调用 * */ if (rightCount > leftCount) { bfsRecu(currParentheses + ')', leftCount, rightCount - 1); } /** * 若是还有剩余左括号数,则将当前存放的括号组合状况添加一个左括号,而后剩余左边括号数减1,而后递归调用便可 */ if (leftCount > 0) { bfsRecu(currParentheses + '(', leftCount - 1, rightCount); } } /** * 深度搜索方式打印括号组合数字 * @param parentheseCount 括号对数 */ public void dfs(int parentheseCount) { if (parentheseCount < 1) { throw new IllegalArgumentException("括号对数不能小于1"); } dfsRecu("", parentheseCount, parentheseCount); } /** * 深度优先搜索递归方法 * @param currParentheses 当前存放的括号组合状况 * @param leftCount 剩余左括号数 * @param rightCount 剩余右括号数 */ private void dfsRecu(String currParentheses, int leftCount, int rightCount) { /** * 结束条件: * 当剩余括号数和剩余右括号数都为0时,表示括号已经用完,直接输出就能够打印出一种状况 */ if (leftCount == 0 && rightCount == 0) { System.out.println(currParentheses); } /** * 深度优先搜索的目的是尽量先获取左边括号, 这种状况下, 若是剩余左括号数大于0,则 * 将当前存放的括号组合状况添加一个左括号,而后剩余左边括号数减1,而后递归调用 * */ if (leftCount > 0) { dfsRecu(currParentheses + '(', leftCount - 1, rightCount); } /** * 检查剩余的右括号数是否大于剩余的左括号数,若是大于, * 则将当前存放的括号组合状况添加一个右括号,而后右边括号数减1,而后递归调用 * */ if (rightCount > leftCount) { dfsRecu(currParentheses + ')', leftCount, rightCount - 1); } } }
/** * @author wangmengjun * */ public class Main { public static void main(String[] args) { ParenthesesPrinter example = new ParenthesesPrinter(); for (int i = 2; i <= 5; i++) { System.out.println(String.format("广度优先搜索, %d对括号全部的可能组合,", i)); example.bfs(i); System.out.println(); System.out.println(String.format("深度优先搜索, %d对括号全部的可能组合,", i)); example.dfs(i); System.out.println(); } } }
运行结果以下:
广度优先搜索, 2对括号全部的可能组合, ()() (()) 深度优先搜索, 2对括号全部的可能组合, (()) ()() 广度优先搜索, 3对括号全部的可能组合, ()()() ()(()) (())() (()()) ((())) 深度优先搜索, 3对括号全部的可能组合, ((())) (()()) (())() ()(()) ()()() 广度优先搜索, 4对括号全部的可能组合, ()()()() ()()(()) ()(())() ()(()()) ()((())) (())()() (())(()) (()())() (()()()) (()(())) ((()))() ((())()) ((()())) (((()))) 深度优先搜索, 4对括号全部的可能组合, (((()))) ((()())) ((())()) ((()))() (()(())) (()()()) (()())() (())(()) (())()() ()((())) ()(()()) ()(())() ()()(()) ()()()() 广度优先搜索, 5对括号全部的可能组合, ()()()()() ()()()(()) ()()(())() ()()(()()) ()()((())) ()(())()() ()(())(()) ()(()())() ()(()()()) ()(()(())) ()((()))() ()((())()) ()((()())) ()(((()))) (())()()() (())()(()) (())(())() (())(()()) (())((())) (()())()() (()())(()) (()()())() (()()()()) (()()(())) (()(()))() (()(())()) (()(()())) (()((()))) ((()))()() ((()))(()) ((())())() ((())()()) ((())(())) ((()()))() ((()())()) ((()()())) ((()(()))) (((())))() (((()))()) (((())())) (((()()))) ((((())))) 深度优先搜索, 5对括号全部的可能组合, ((((())))) (((()()))) (((())())) (((()))()) (((())))() ((()(()))) ((()()())) ((()())()) ((()()))() ((())(())) ((())()()) ((())())() ((()))(()) ((()))()() (()((()))) (()(()())) (()(())()) (()(()))() (()()(())) (()()()()) (()()())() (()())(()) (()())()() (())((())) (())(()()) (())(())() (())()(()) (())()()() ()(((()))) ()((()())) ()((())()) ()((()))() ()(()(())) ()(()()()) ()(()())() ()(())(()) ()(())()() ()()((())) ()()(()()) ()()(())() ()()()(()) ()()()()()