博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA算法:括号配对问题与卡塔兰数(Catalan number)
阅读量:4039 次
发布时间:2019-05-24

本文共 4555 字,大约阅读时间需要 15 分钟。

JAVA算法:括号配对问题与卡塔兰数(Catalan number)

LeetCode中第22题目:22. Generate Parentheses

原题链接:

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

[

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

这道题目大意是:给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。


问题分析

求解这个题目并不是很困难。但是要深究这个题目,需要了解什么是卡塔兰数,又可以叫做卡特兰数,英文是:Catalan Number

那么什么是Catalan Number?

百度百科给出的描述为:卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中的数列。以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名。

其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...

 下面是一些典型的问题:(实质上都是递推等式的应用)

  • 括号化:矩阵连乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)  
  • 出栈次序:一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列? 
  • n对括号正确匹配数目。

给定n对括号,求括号正确配对的字符串数,例如:

0对括号:[空序列]—— 1种可能

1对括号:() —— 1种可能

2对括号:()() (()) —— 2种可能

3对括号:((())) ()(()) ()()() (())() (()()) —— 5种可能

那么问题来了,n对括号有多少种正确配对的可能呢?

考虑n对括号时的任意一种配对方案,最后一个右括号有唯一的与之匹配的左括号,于是有唯一的表示A(B),其中A和B也是合法的括号匹配序列。

假设S(n)为n对括号的正确配对数目,那么有递推关系S(n)=S(0)S(n-1)+S(1)S(n-2) +...+S(n-1)S(0),显然S(n)是卡特兰数。


算法设计

使用递归算法求解前20个Catalan Number

package com.bean.algorithm.basic;public class CatalanNumbers2 { // 求卡特兰数	// 使用递归的方式解决卡特兰数	public static long CatalanNumber(int n) {		if (n == 1) {			return 1;		} else {			return CatalanNumber(n - 1) * 2 * (2 * n - 1) / (n + 1);		}	}	public static void main(String[] args) {		//为了防止计算溢出,求前20个Catalan Number		for (int i = 1; i <= 20; i++) {			System.out.println(i + "'s Catalan Number is " + CatalanNumber(i));		}	}}

程序运行结果为:

1's Catalan Number is 1

2's Catalan Number is 2
3's Catalan Number is 5
4's Catalan Number is 14
5's Catalan Number is 42
6's Catalan Number is 132
7's Catalan Number is 429
8's Catalan Number is 1430
9's Catalan Number is 4862
10's Catalan Number is 16796
11's Catalan Number is 58786
12's Catalan Number is 208012
13's Catalan Number is 742900
14's Catalan Number is 2674440
15's Catalan Number is 9694845
16's Catalan Number is 35357670
17's Catalan Number is 129644790
18's Catalan Number is 477638700
19's Catalan Number is 1767263190
20's Catalan Number is 6564120420

另外一种解法:

package com.bean.algorithm.basic;import java.util.*;import java.math.BigInteger;public class CatalanNumbers { // 求卡特兰数	public static void main(String[] args) {		int numberOfCatalan = 101; // 要求多少个卡特兰数		BigInteger[] digis = new BigInteger[numberOfCatalan];		digis = generateCatalan(numberOfCatalan);		System.out.println("请输入需要求解第几个Catalan Number:");		Scanner scanner = new Scanner(System.in);		int number;		while (true) {			number = scanner.nextInt();			if (number == -1)				break;			String answer = digis[number].toString();			System.out.println(answer);		}	}	static BigInteger[] generateCatalan(int numberOfCatalan) {		// 产生卡特兰数		BigInteger digis[] = new BigInteger[numberOfCatalan + 1];		BigInteger x = new BigInteger("1"); // 第一个卡特兰数为1		digis[1] = x;		int y = 0;		int z = 0;		for (int counter = 2; counter <= numberOfCatalan; ++counter) {			y = 4 * counter - 2;			z = counter + 1;			digis[counter] = digis[counter - 1].multiply(new BigInteger("" + y));			digis[counter] = digis[counter].divide(new BigInteger("" + z));		}		return digis;	}}

程序运行结果:

请输入需要求解第几个Catalan Number:

5
42

LeetCode第 20 题 的解法:

采用DFS算法求解:

package com.bean.algorithmbasic;import java.util.Iterator;import java.util.LinkedList;import java.util.List;public class GenerateParenthesesDemo {	public List
generateParenthesis(int n) { List
result = new LinkedList
(); if (n > 0) dfs("", n, n, result); return result; } /* * DFS算法设计 * */ private void dfs(String prefix, int left, int right, List
result) { if (left == 0 && right == 0) result.add(prefix); // Has left Parenthesis if (left > 0) dfs(prefix + '(', left - 1, right, result); // has more right Parenthesis if (left < right) dfs(prefix + ')', left, right - 1, result); } public static void main(String[] args) { // TODO Auto-generated method stub int n = 4; GenerateParenthesesDemo gpd = new GenerateParenthesesDemo(); List
list = gpd.generateParenthesis(n); Iterator
itx = list.iterator(); while (itx.hasNext()) { String str = itx.next(); System.out.println(str); } System.out.println("有 "+list.size()+" 种配对方案..."); }}

程序运行结果:

(((())))

((()()))
((())())
((()))()
(()(()))
(()()())
(()())()
(())(())
(())()()
()((()))
()(()())
()(())()
()()(())
()()()()
有 14 种配对方案...

 

转载地址:http://jntdi.baihongyu.com/

你可能感兴趣的文章
drwtsn32.exe和adplus.vbs进行dump文件抓取
查看>>
cppcheck c++静态代码检查
查看>>
在C++中使用Lua
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
昨夜今晨最大八卦终于坐实——人类首次直接探测到了引力波
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.147 - LeetCode1108
查看>>
No.174 - LeetCode1305 - 合并两个搜索树
查看>>
No.175 - LeetCode1306
查看>>
No.176 - LeetCode1309
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
mysql:sql create database新建utf8mb4 数据库
查看>>