加泰罗尼亚数是一系列自然数,出现在许多有趣的计数问题中,例如以下。
- 计算包含正确匹配的 n 对括号的表达式的数量。对于 n = 3,可能的表达式为 ((()))、()(())、()()()、(())()、(()())。
- 用 n 个键计算可能的二叉搜索树的数量(见这个)
- 计算具有 n+1 个叶子的完整二叉树的数量(如果每个顶点有两个孩子或没有孩子,则有根二叉树是满的)。
- 给定一个数字 n,返回您可以在具有 2 xn 个点的圆中绘制 n 个和弦的方法数,这样没有 2 个和弦相交。
有关更多应用,请参见此处。
n = 0, 1, 2, 3, … 的前几个加泰罗尼亚数是1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, …
递归解
加泰罗尼亚数满足以下递归公式。
以下是上述递归公式的实现。
C++
#include
using namespace std;
// A recursive function to find nth catalan number
unsigned long int catalan(unsigned int n)
{
// Base case
if (n <= 1)
return 1;
// catalan(n) is sum of
// catalan(i)*catalan(n-i-1)
unsigned long int res = 0;
for (int i = 0; i < n; i++)
res += catalan(i)
* catalan(n - i - 1);
return res;
}
// Driver code
int main()
{
for (int i = 0; i < 10; i++)
cout << catalan(i) << " ";
return 0;
}
Java
class CatalnNumber {
// A recursive function to find nth catalan number
int catalan(int n)
{
int res = 0;
// Base case
if (n <= 1)
{
return 1;
}
for (int i = 0; i < n; i++)
{
res += catalan(i)
* catalan(n - i - 1);
}
return res;
}
// Driver Code
public static void main(String[] args)
{
CatalnNumber cn = new CatalnNumber();
for (int i = 0; i < 10; i++)
{
System.out.print(cn.catalan(i) + " ");
}
}
}
Python
# A recursive function to
# find nth catalan number
def catalan(n):
# Base Case
if n <= 1:
return 1
# Catalan(n) is the sum
# of catalan(i)*catalan(n-i-1)
res = 0
for i in range(n):
res += catalan(i) * catalan(n-i-1)
return res
# Driver Code
for i in range(10):
print catalan(i),
# This code is contributed by
# Nikhil Kumar Singh (nickzuck_007)
C#
// A recursive C# program to find
// nth catalan number
using System;
class GFG {
// A recursive function to find
// nth catalan number
static int catalan(int n)
{
int res = 0;
// Base case
if (n <= 1)
{
return 1;
}
for (int i = 0; i < n; i++)
{
res += catalan(i)
* catalan(n - i - 1);
}
return res;
}
// Driver Code
public static void Main()
{
for (int i = 0; i < 10; i++)
Console.Write(catalan(i) + " ");
}
}
// This code is contributed by
// nitin mittal.
PHP
Javascript
C++
#include
using namespace std;
// A dynamic programming based function to find nth
// Catalan number
unsigned long int catalanDP(unsigned int n)
{
// Table to store results of subproblems
unsigned long int catalan[n + 1];
// Initialize first two values in table
catalan[0] = catalan[1] = 1;
// Fill entries in catalan[] using recursive formula
for (int i = 2; i <= n; i++) {
catalan[i] = 0;
for (int j = 0; j < i; j++)
catalan[i] += catalan[j] * catalan[i - j - 1];
}
// Return last entry
return catalan[n];
}
// Driver code
int main()
{
for (int i = 0; i < 10; i++)
cout << catalanDP(i) << " ";
return 0;
}
Java
class GFG {
// A dynamic programming based function to find nth
// Catalan number
static int catalanDP(int n)
{
// Table to store results of subproblems
int catalan[] = new int[n + 2];
// Initialize first two values in table
catalan[0] = 1;
catalan[1] = 1;
// Fill entries in catalan[]
// using recursive formula
for (int i = 2; i <= n; i++) {
catalan[i] = 0;
for (int j = 0; j < i; j++) {
catalan[i]
+= catalan[j] * catalan[i - j - 1];
}
}
// Return last entry
return catalan[n];
}
// Driver code
public static void main(String[] args)
{
for (int i = 0; i < 10; i++) {
System.out.print(catalanDP(i) + " ");
}
}
}
// This code contributed by Rajput-Ji
Python3
# A dynamic programming based function to find nth
# Catalan number
def catalan(n):
if (n == 0 or n == 1):
return 1
# Table to store results of subproblems
catalan =[0]*(n+1)
# Initialize first two values in table
catalan[0] = 1
catalan[1] = 1
# Fill entries in catalan[]
# using recursive formula
for i in range(2, n + 1):
for j in range(i):
catalan[i] += catalan[j]* catalan[i-j-1]
# Return last entry
return catalan[n]
# Driver code
for i in range(10):
print(catalan(i), end=" ")
# This code is contributed by Ediga_manisha
C#
using System;
class GFG {
// A dynamic programming based
// function to find nth
// Catalan number
static uint catalanDP(uint n)
{
// Table to store results of subproblems
uint[] catalan = new uint[n + 2];
// Initialize first two values in table
catalan[0] = catalan[1] = 1;
// Fill entries in catalan[]
// using recursive formula
for (uint i = 2; i <= n; i++) {
catalan[i] = 0;
for (uint j = 0; j < i; j++)
catalan[i]
+= catalan[j] * catalan[i - j - 1];
}
// Return last entry
return catalan[n];
}
// Driver code
static void Main()
{
for (uint i = 0; i < 10; i++)
Console.Write(catalanDP(i) + " ");
}
}
// This code is contributed by Chandan_jnu
PHP
Javascript
C++
// C++ program for nth Catalan Number
#include
using namespace std;
// Returns value of Binomial Coefficient C(n, k)
unsigned long int binomialCoeff(unsigned int n,
unsigned int k)
{
unsigned long int res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k)
k = n - k;
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function to find nth catalan
// number in O(n) time
unsigned long int catalan(unsigned int n)
{
// Calculate value of 2nCn
unsigned long int c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
int main()
{
for (int i = 0; i < 10; i++)
cout << catalan(i) << " ";
return 0;
}
Java
// Java program for nth Catalan Number
class GFG {
// Returns value of Binomial Coefficient C(n, k)
static long binomialCoeff(int n, int k)
{
long res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k) {
k = n - k;
}
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function
// to find nth catalan number in O(n) time
static long catalan(int n)
{
// Calculate value of 2nCn
long c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
public static void main(String[] args)
{
for (int i = 0; i < 10; i++) {
System.out.print(catalan(i) + " ");
}
}
}
Python3
# Python program for nth Catalan Number
# Returns value of Binomial Coefficient C(n, k)
def binomialCoefficient(n, k):
# since C(n, k) = C(n, n - k)
if (k > n - k):
k = n - k
# initialize result
res = 1
# Calculate value of [n * (n-1) *---* (n-k + 1)]
# / [k * (k-1) *----* 1]
for i in range(k):
res = res * (n - i)
res = res / (i + 1)
return res
# A Binomial coefficient based function to
# find nth catalan number in O(n) time
def catalan(n):
c = binomialCoefficient(2*n, n)
return c/(n + 1)
# Driver Code
for i in range(10):
print(catalan(i), end=" ")
# This code is contributed by Aditi Sharma
C#
// C# program for nth Catalan Number
using System;
class GFG {
// Returns value of Binomial Coefficient C(n, k)
static long binomialCoeff(int n, int k)
{
long res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k) {
k = n - k;
}
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function to find nth
// catalan number in O(n) time
static long catalan(int n)
{
// Calculate value of 2nCn
long c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
public static void Main()
{
for (int i = 0; i < 10; i++) {
Console.Write(catalan(i) + " ");
}
}
}
// This code is contributed
// by Akanksha Rai
PHP
$n - $k)
$k = $n - $k;
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for ($i = 0; $i < $k; ++$i)
{
$res *= ($n - $i);
$res = floor($res / ($i + 1));
}
return $res;
}
// A Binomial coefficient based function
// to find nth catalan number in O(n) time
function catalan($n)
{
// Calculate value of 2nCn
$c = binomialCoeff(2 * ($n), $n);
// return 2nCn/(n+1)
return floor($c / ($n + 1));
}
// Driver code
for ($i = 0; $i < 10; $i++)
echo catalan($i), " " ;
// This code is contributed by Ryuga
?>
Javascript
C++
#include
#include
using boost::multiprecision::cpp_int;
using namespace std;
// Function to print the number
void catalan(int n)
{
cpp_int cat_ = 1;
// For the first number
cout << cat_ << " "; // C(0)
// Iterate till N
for (cpp_int i = 1; i < n; i++)
{
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
cout << cat_ << " ";
}
}
// Driver code
int main()
{
int n = 5;
// Function call
catalan(n);
return 0;
}
Java
import java.util.*;
class GFG
{
// Function to print the number
static void catalan(int n)
{
int cat_ = 1;
// For the first number
System.out.print(cat_+" "); // C(0)
// Iterate till N
for (int i = 1; i < n; i++)
{
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
System.out.print(cat_+" ");
}
}
// Driver code
public static void main(String args[])
{
int n = 5;
// Function call
catalan(n);
}
}
// This code is contributed by Debojyoti Mandal
Python3
# Function to print the number
def catalan(n):
cat_ = 1
# For the first number
print(cat_, " ", end = '')# C(0)
# Iterate till N
for i in range(1, n):
# Calculate the number
# and print it
cat_ *= (4 * i - 2);
cat_ //= (i + 1);
print(cat_, " ", end = '')
# Driver code
n = 5
# Function call
catalan(n)
# This code is contributed by rohan07
C#
using System;
public class GFG {
// Function to print the number
static void catalan(int n) {
int cat_ = 1;
// For the first number
Console.Write(cat_ + " "); // C(0)
// Iterate till N
for (int i = 1; i < n; i++) {
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
Console.Write(cat_ + " ");
}
}
// Driver code
public static void Main(String []args) {
int n = 5;
// Function call
catalan(n);
}
}
// This code is contributed by Rajput-Ji
Javascript
Java
import java.io.*;
import java.util.*;
import java.math.*;
class GFG
{
public static BigInteger findCatalan(int n)
{
// using BigInteger to calculate large factorials
BigInteger b = new BigInteger("1");
// calculating n!
for (int i = 1; i <= n; i++) {
b = b.multiply(BigInteger.valueOf(i));
}
// calculating n! * n!
b = b.multiply(b);
BigInteger d = new BigInteger("1");
// calculating (2n)!
for (int i = 1; i <= 2 * n; i++) {
d = d.multiply(BigInteger.valueOf(i));
}
// calculating (2n)! / (n! * n!)
BigInteger ans = d.divide(b);
// calculating (2n)! / ((n! * n!) * (n+1))
ans = ans.divide(BigInteger.valueOf(n + 1));
return ans;
}
// Driver Code
public static void main(String[] args)
{
int n = 5;
System.out.println(findCatalan(n));
}
}
// Contributed by Rohit Oberoi
1 1 2 5 14 42 132 429 1430 4862
上述实现的时间复杂度相当于第 n 个加泰罗尼亚数。
第 n 个 catalan 数的值是指数的,这使得时间复杂度呈指数。
动态规划解决方案:我们可以观察到上面的递归实现做了很多重复的工作(我们可以通过绘制递归树来做同样的工作)。由于存在重叠的子问题,我们可以使用动态规划来解决这个问题。以下是基于动态编程的实现。
C++
#include
using namespace std;
// A dynamic programming based function to find nth
// Catalan number
unsigned long int catalanDP(unsigned int n)
{
// Table to store results of subproblems
unsigned long int catalan[n + 1];
// Initialize first two values in table
catalan[0] = catalan[1] = 1;
// Fill entries in catalan[] using recursive formula
for (int i = 2; i <= n; i++) {
catalan[i] = 0;
for (int j = 0; j < i; j++)
catalan[i] += catalan[j] * catalan[i - j - 1];
}
// Return last entry
return catalan[n];
}
// Driver code
int main()
{
for (int i = 0; i < 10; i++)
cout << catalanDP(i) << " ";
return 0;
}
Java
class GFG {
// A dynamic programming based function to find nth
// Catalan number
static int catalanDP(int n)
{
// Table to store results of subproblems
int catalan[] = new int[n + 2];
// Initialize first two values in table
catalan[0] = 1;
catalan[1] = 1;
// Fill entries in catalan[]
// using recursive formula
for (int i = 2; i <= n; i++) {
catalan[i] = 0;
for (int j = 0; j < i; j++) {
catalan[i]
+= catalan[j] * catalan[i - j - 1];
}
}
// Return last entry
return catalan[n];
}
// Driver code
public static void main(String[] args)
{
for (int i = 0; i < 10; i++) {
System.out.print(catalanDP(i) + " ");
}
}
}
// This code contributed by Rajput-Ji
蟒蛇3
# A dynamic programming based function to find nth
# Catalan number
def catalan(n):
if (n == 0 or n == 1):
return 1
# Table to store results of subproblems
catalan =[0]*(n+1)
# Initialize first two values in table
catalan[0] = 1
catalan[1] = 1
# Fill entries in catalan[]
# using recursive formula
for i in range(2, n + 1):
for j in range(i):
catalan[i] += catalan[j]* catalan[i-j-1]
# Return last entry
return catalan[n]
# Driver code
for i in range(10):
print(catalan(i), end=" ")
# This code is contributed by Ediga_manisha
C#
using System;
class GFG {
// A dynamic programming based
// function to find nth
// Catalan number
static uint catalanDP(uint n)
{
// Table to store results of subproblems
uint[] catalan = new uint[n + 2];
// Initialize first two values in table
catalan[0] = catalan[1] = 1;
// Fill entries in catalan[]
// using recursive formula
for (uint i = 2; i <= n; i++) {
catalan[i] = 0;
for (uint j = 0; j < i; j++)
catalan[i]
+= catalan[j] * catalan[i - j - 1];
}
// Return last entry
return catalan[n];
}
// Driver code
static void Main()
{
for (uint i = 0; i < 10; i++)
Console.Write(catalanDP(i) + " ");
}
}
// This code is contributed by Chandan_jnu
PHP
Javascript
1 1 2 5 14 42 132 429 1430 4862
时间复杂度:上述实现的时间复杂度为 O(n 2 )
使用二项式系数
我们也可以使用下面的公式在 O(n) 时间内找到第 n 个加泰罗尼亚数。
我们已经讨论了一种 O(n) 方法来找到二项式系数 nCr。
C++
// C++ program for nth Catalan Number
#include
using namespace std;
// Returns value of Binomial Coefficient C(n, k)
unsigned long int binomialCoeff(unsigned int n,
unsigned int k)
{
unsigned long int res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k)
k = n - k;
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function to find nth catalan
// number in O(n) time
unsigned long int catalan(unsigned int n)
{
// Calculate value of 2nCn
unsigned long int c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
int main()
{
for (int i = 0; i < 10; i++)
cout << catalan(i) << " ";
return 0;
}
Java
// Java program for nth Catalan Number
class GFG {
// Returns value of Binomial Coefficient C(n, k)
static long binomialCoeff(int n, int k)
{
long res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k) {
k = n - k;
}
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function
// to find nth catalan number in O(n) time
static long catalan(int n)
{
// Calculate value of 2nCn
long c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
public static void main(String[] args)
{
for (int i = 0; i < 10; i++) {
System.out.print(catalan(i) + " ");
}
}
}
蟒蛇3
# Python program for nth Catalan Number
# Returns value of Binomial Coefficient C(n, k)
def binomialCoefficient(n, k):
# since C(n, k) = C(n, n - k)
if (k > n - k):
k = n - k
# initialize result
res = 1
# Calculate value of [n * (n-1) *---* (n-k + 1)]
# / [k * (k-1) *----* 1]
for i in range(k):
res = res * (n - i)
res = res / (i + 1)
return res
# A Binomial coefficient based function to
# find nth catalan number in O(n) time
def catalan(n):
c = binomialCoefficient(2*n, n)
return c/(n + 1)
# Driver Code
for i in range(10):
print(catalan(i), end=" ")
# This code is contributed by Aditi Sharma
C#
// C# program for nth Catalan Number
using System;
class GFG {
// Returns value of Binomial Coefficient C(n, k)
static long binomialCoeff(int n, int k)
{
long res = 1;
// Since C(n, k) = C(n, n-k)
if (k > n - k) {
k = n - k;
}
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// A Binomial coefficient based function to find nth
// catalan number in O(n) time
static long catalan(int n)
{
// Calculate value of 2nCn
long c = binomialCoeff(2 * n, n);
// return 2nCn/(n+1)
return c / (n + 1);
}
// Driver code
public static void Main()
{
for (int i = 0; i < 10; i++) {
Console.Write(catalan(i) + " ");
}
}
}
// This code is contributed
// by Akanksha Rai
PHP
$n - $k)
$k = $n - $k;
// Calculate value of [n*(n-1)*---*(n-k+1)] /
// [k*(k-1)*---*1]
for ($i = 0; $i < $k; ++$i)
{
$res *= ($n - $i);
$res = floor($res / ($i + 1));
}
return $res;
}
// A Binomial coefficient based function
// to find nth catalan number in O(n) time
function catalan($n)
{
// Calculate value of 2nCn
$c = binomialCoeff(2 * ($n), $n);
// return 2nCn/(n+1)
return floor($c / ($n + 1));
}
// Driver code
for ($i = 0; $i < 10; $i++)
echo catalan($i), " " ;
// This code is contributed by Ryuga
?>
Javascript
1 1 2 5 14 42 132 429 1430 4862
时间复杂度:上述实现的时间复杂度为 O(n)。
我们还可以使用下面的公式在 O(n) 时间内找到第 n 个加泰罗尼亚数。
使用多精度库:在这种方法中,我们使用了boost多精度库,其使用的动机只是为了在找到大CATALAN数的同时具有精度和使用for循环计算Catalan数的通用技术。
For example: N = 5
Initially set cat_=1 then, print cat_ ,
then, iterate from i = 1 to i < 5
for i = 1; cat_ = cat_ * (4*1-2)=1*2=2
cat_ = cat_ / (i+1)=2/2 = 1
For i = 2; cat_ = cat_ * (4*2-2)=1*6=6
cat_ = cat_ / (i+1)=6/3=2
For i = 3 :- cat_ = cat_ * (4*3-2)=2*10=20
cat_ = cat_ / (i+1)=20/4=5
For i = 4 :- cat_ = cat_ * (4*4-2)=5*14=70
cat_ = cat_ / (i+1)=70/5=14
伪代码:
a) initially set cat_=1 and print it
b) run a for loop i=1 to i<=n
cat_ *= (4*i-2)
cat_ /= (i+1)
print cat_
c) end loop and exit
C++
#include
#include
using boost::multiprecision::cpp_int;
using namespace std;
// Function to print the number
void catalan(int n)
{
cpp_int cat_ = 1;
// For the first number
cout << cat_ << " "; // C(0)
// Iterate till N
for (cpp_int i = 1; i < n; i++)
{
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
cout << cat_ << " ";
}
}
// Driver code
int main()
{
int n = 5;
// Function call
catalan(n);
return 0;
}
Java
import java.util.*;
class GFG
{
// Function to print the number
static void catalan(int n)
{
int cat_ = 1;
// For the first number
System.out.print(cat_+" "); // C(0)
// Iterate till N
for (int i = 1; i < n; i++)
{
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
System.out.print(cat_+" ");
}
}
// Driver code
public static void main(String args[])
{
int n = 5;
// Function call
catalan(n);
}
}
// This code is contributed by Debojyoti Mandal
蟒蛇3
# Function to print the number
def catalan(n):
cat_ = 1
# For the first number
print(cat_, " ", end = '')# C(0)
# Iterate till N
for i in range(1, n):
# Calculate the number
# and print it
cat_ *= (4 * i - 2);
cat_ //= (i + 1);
print(cat_, " ", end = '')
# Driver code
n = 5
# Function call
catalan(n)
# This code is contributed by rohan07
C#
using System;
public class GFG {
// Function to print the number
static void catalan(int n) {
int cat_ = 1;
// For the first number
Console.Write(cat_ + " "); // C(0)
// Iterate till N
for (int i = 1; i < n; i++) {
// Calculate the number
// and print it
cat_ *= (4 * i - 2);
cat_ /= (i + 1);
Console.Write(cat_ + " ");
}
}
// Driver code
public static void Main(String []args) {
int n = 5;
// Function call
catalan(n);
}
}
// This code is contributed by Rajput-Ji
Javascript
1 1 2 5 14
时间复杂度: O(n)
辅助空间: O(1)
在Java使用 BigInteger 的另一种解决方案:
- 即使在Java使用 long 也无法找到 N>80 的加泰罗尼亚数字的值,因此我们使用 BigInteger
- 在这里,我们使用上面讨论的二项式系数方法找到解决方案
Java
import java.io.*;
import java.util.*;
import java.math.*;
class GFG
{
public static BigInteger findCatalan(int n)
{
// using BigInteger to calculate large factorials
BigInteger b = new BigInteger("1");
// calculating n!
for (int i = 1; i <= n; i++) {
b = b.multiply(BigInteger.valueOf(i));
}
// calculating n! * n!
b = b.multiply(b);
BigInteger d = new BigInteger("1");
// calculating (2n)!
for (int i = 1; i <= 2 * n; i++) {
d = d.multiply(BigInteger.valueOf(i));
}
// calculating (2n)! / (n! * n!)
BigInteger ans = d.divide(b);
// calculating (2n)! / ((n! * n!) * (n+1))
ans = ans.divide(BigInteger.valueOf(n + 1));
return ans;
}
// Driver Code
public static void main(String[] args)
{
int n = 5;
System.out.println(findCatalan(n));
}
}
// Contributed by Rohit Oberoi
42
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。