Algorithm 如何打印表达式的所有可能的平衡圆括号?
例如,对于元素Algorithm 如何打印表达式的所有可能的平衡圆括号?,algorithm,puzzle,catalan,Algorithm,Puzzle,Catalan,例如,对于元素a、b、c、d,有5种可能的方法可以将相邻元素合并为一个元素,其中一次必须合并两个元素(下面用括号表示): 第一个示例将a*b相乘,然后将该乘积乘以c,然后将该乘积乘以d。第二个示例首先将b*c相乘,然后将该乘积乘以a,然后将该乘积乘以d 2n个元素的任何有效括号表达式都必须有n(和n),其属性是,从左到右读取时,始终至少有与相同数量的() 我知道对于n个数,方法数是第(n-1)个。但是如何准确地生成所有结果分组呢 谢谢 (顺便提一下:这个问题有160多个等价的公式,都是基于加泰罗
a、b、c、d
,有5种可能的方法可以将相邻元素合并为一个元素,其中一次必须合并两个元素(下面用括号表示):
第一个示例将a*b
相乘,然后将该乘积乘以c
,然后将该乘积乘以d
。第二个示例首先将b*c
相乘,然后将该乘积乘以a
,然后将该乘积乘以d
2n个元素的任何有效括号表达式都必须有n(
和n)
,其属性是,从左到右读取时,始终至少有与相同数量的(
)
我知道对于n个数,方法数是第(n-1)个。但是如何准确地生成所有结果分组呢
谢谢
(顺便提一下:这个问题有160多个等价的公式,都是基于加泰罗尼亚数字列举的不同组合对象。最新的列表,请参见。)递归将是一种方法 将abcd拆分为
(a) (bcd)
(ab) (cd)
(abc) (d)
这些是一些可能性
现在,您可以递归地拆分每个字符串(拆分时忽略括号),例如(bcd)一种可能性
(b) (cd)
所以现在另一个组合是
((a)(b)(cd))
一旦得到一个只有一个字母的字符串,就可以停止递归树
for each balanced expression of n-1 parentheses
for each pos i from 0 to m of an expression
add '('
for each pos j from i + 1 to m
add ')' if expression is balanced
您将获得以下订单:
n=0:
n=1: ()
n=2: []() , [()]
n=3: {}[]() , {[]}() , {[]()} , {}[()] , {[()]}
在这里,我每次都要更改参数,
(,[,{
,以突出显示算法的工作原理。这里是Python中的实际代码,使用生成器以避免使用太多内存
#! /usr/bin/python
def parenthesized (exprs):
if len(exprs) == 1:
yield exprs[0]
else:
first_exprs = []
last_exprs = list(exprs)
while 1 < len(last_exprs):
first_exprs.append(last_exprs.pop(0))
for x in parenthesized(first_exprs):
if 1 < len(first_exprs):
x = '(%s)' % x
for y in parenthesized(last_exprs):
if 1 < len(last_exprs):
y = '(%s)' % y
yield '%s%s' % (x, y)
for x in parenthesized(['a', 'b', 'c', 'd']):
print x
!/usr/bin/python
括号内的def(表达式):
如果len(exprs)==1:
收益率表达式[0]
其他:
第一个表达式=[]
最后的exprs=列表(exprs)
而1
实际上,4个元素中有5个以上的括号;你实际上不是指“括号”。你真正想问的是N个元素可以通过多少种不同的方式减少d,或者在保持它们有序的情况下,你可以从N个元素中生成多少棵树。
这对应于将表达式精确地细分N-1次。例如,在维基百科文章中的这幅图中,如果我们有4个元素,则有5种方法可以对其应用二进制运算符(需要有3个应用程序,因此有3个节点):
例如,((a*b)*c)*d,(a*(b*c))*d,(a*b)*(c*d),a*((b*c)*d),a*(b*(c*d))
下面是一些简洁的python代码:
def associations(seq, **kw):
"""
>>> associations([1,2,3,4])
[(1, (2, (3, 4))), (1, ((2, 3), 4)), ((1, 2), (3, 4)), ((1, (2, 3)), 4), (((1, 2), 3), 4)]
"""
grouper = kw.get('grouper', lambda a,b:(a,b))
lifter = kw.get('lifter', lambda x:x)
if len(seq)==1:
yield lifter(seq[0])
else:
for i in range(len(seq)):
left,right = seq[:i],seq[i:] # split sequence on index i
# return cartesian product of left x right
for l in associations(left,**kw):
for r in associations(right,**kw):
yield grouper(l,r)
请注意如何用此代码替换grouper
的有趣函数,例如grouper=list
,或grouper=Tree
,或grouper=…
演示:
和,这里有一些C++代码,同样:
bool is_a_solution( string partial,int n,int k) {
if(partial.length() == n*2 )
return true;
return false;
}
string constructCandidate(int n,string input,string partial, int k) {
int xcount=0,ycount=0;
int count;
int i;
string candi;
if(k == 0)
return string("(");
else {
for(i=0;i<partial.length();i++) {
if( partial[i] == '(') xcount++;
if( partial[i] == ')') ycount++;
}
if( xcount <n) candi+="(";
if( ycount < xcount) candi+=")";
}
return candi;} void backTrack(int n,string input, string partial,int k ) {
int i, numCanditate;
string mypartial;
if( is_a_solution(partial,n,k)) {
cout <<partial<<"\n";
}else {
string candi=constructCandidate(n,input,partial,k);
for(i=0;i<candi.length();i++) {
backTrack(n,input,partial+candi[i],k+1);
}
}
void paranthesisPrint(int n){
backTrack(n,"()", "",0);
}
bool是一个解(字符串部分,int n,int k){
if(partial.length()==n*2)
返回true;
返回false;
}
字符串构造候选(int n,字符串输入,字符串部分,int k){
int xcount=0,ycount=0;
整数计数;
int i;
串坎迪;
如果(k==0)
返回字符串(“”);
否则{
对于(i=0;iimport java.util.ArrayList;
公开课论文{
私人ArrayList parStringList;
私人整数合计;
public void explorerPartnerThese(字符串parString、int-leftCnt、int-righcnt)
{
如果(左Cnt<总计)
{
exploreParantheses(parString+“(”,leftCnt+1,righcnt);
}
如果((右Cnt
*
**运行此命令生成所有论文:
//苏多苏汉
#包括
#包括
#包括
#定义最大尺寸200
void _print括号(int pos,int n1,int open1,int close1,int n2,int open2,int close2,int n3,int open3,int close3);
无效打印括号(int n1、int n2、int n3)
{
如果(n1>0 | | n2>0 | | n3>0)
_打印括号(0,n1,0,0,n2,0,0,n3,0,0);
返回;
}
void _print括号(int pos,int n1,int open1,int close1,int n2,int open2,int close2,int n3,int open3,int close3)
{
静态字符str[MAX_SIZE];
if(close1==n1&&close2==n2&&close3==n3)
{
printf(“%s\n”,str);
返回;
}
其他的
{
bool run1=open1>close1;
bool run2=open2>close2;
bool run3=open3>close3;
如果(运行3)
{
str[pos]=')';
_打印括号(位置+1,n1,打开1,关闭1,n2,打开2,关闭2,n3,打开3,关闭3+1);
如果(open3for assoc in associations('abcd'):
print assoc
('a', ('b', ('c', 'd')))
('a', (('b', 'c'), 'd'))
(('a', 'b'), ('c', 'd'))
(('a', ('b', 'c')), 'd')
((('a', 'b'), 'c'), 'd')
bool is_a_solution( string partial,int n,int k) {
if(partial.length() == n*2 )
return true;
return false;
}
string constructCandidate(int n,string input,string partial, int k) {
int xcount=0,ycount=0;
int count;
int i;
string candi;
if(k == 0)
return string("(");
else {
for(i=0;i<partial.length();i++) {
if( partial[i] == '(') xcount++;
if( partial[i] == ')') ycount++;
}
if( xcount <n) candi+="(";
if( ycount < xcount) candi+=")";
}
return candi;} void backTrack(int n,string input, string partial,int k ) {
int i, numCanditate;
string mypartial;
if( is_a_solution(partial,n,k)) {
cout <<partial<<"\n";
}else {
string candi=constructCandidate(n,input,partial,k);
for(i=0;i<candi.length();i++) {
backTrack(n,input,partial+candi[i],k+1);
}
}
void paranthesisPrint(int n){
backTrack(n,"()", "",0);
}
import java.util.ArrayList;
public class Parantheses {
private ArrayList<String> parStringList;
private int total;
public void exploreParantheses(String parString,int leftCnt,int rightCnt)
{
if (leftCnt < total)
{
exploreParantheses(parString + "(", leftCnt+1, rightCnt);
}
if ((rightCnt < total) &&(rightCnt < leftCnt))
{
exploreParantheses(parString + ")", leftCnt, rightCnt+1);
}
else if (rightCnt == total)
{
parStringList.add(parString);
}
}
public ArrayList<String> generateParanthesis(int numPars)
{
this.total = numPars;
this.parStringList = new ArrayList<String>();
exploreParantheses("", 0, 0);
return this.parStringList;
}
public static void main(String args[])
{
ArrayList<String> par;
par = (new Parantheses()).generateParanthesis(6);
for (String str: par)
System.out.println(str);
}
}
**Run this to generate all balanced parantheses:
//sudosuhan
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MAX_SIZE 200
void _printParenthesis(int pos, int n1, int open1, int close1, int n2, int open2, int close2, int n3, int open3, int close3);
void printParenthesis(int n1 , int n2 , int n3 )
{
if(n1 > 0 || n2 > 0 || n3 > 0)
_printParenthesis(0, n1, 0, 0, n2, 0, 0, n3, 0, 0);
return;
}
void _printParenthesis(int pos, int n1, int open1, int close1, int n2, int open2, int close2, int n3, int open3, int close3)
{
static char str[MAX_SIZE];
if(close1 == n1 && close2 == n2 && close3 == n3 )
{
printf("%s \n", str);
return;
}
else
{
bool run1 = open1 > close1;
bool run2 = open2 > close2;
bool run3 = open3 > close3;
if(run3)
{
str[pos] = ')';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2, n3, open3, close3+1);
if(open3 < n3)
{
str[pos] = '(';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2, n3, open3+1, close3);
}
}
else if(run2 && !run3)
{
str[pos] = '}';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2+1, n3, open3, close3);
if(open3 < n3)
{
str[pos] = '(';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2, n3, open3+1, close3);
}
if(open2 < n2)
{
str[pos] = '{';
_printParenthesis(pos+1, n1, open1, close1, n2, open2+1, close2, n3, open3, close3);
}
}
else if(run1 && !run2 && !run3)
{
str[pos] = ']';
_printParenthesis(pos+1, n1, open1, close1+1, n2, open2, close2, n3, open3, close3);
if(open3 < n3)
{
str[pos] = '(';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2, n3, open3+1, close3);
}
if(open2 < n2)
{
str[pos] = '{';
_printParenthesis(pos+1, n1, open1, close1, n2, open2+1, close2, n3, open3, close3);
}
if(open1 < n1)
{
str[pos] = '[';
_printParenthesis(pos+1, n1, open1+1, close1, n2, open2, close2, n3, open3, close3);
}
}
else if(!run1 && !run2 && !run3)
{
if(open3 < n3)
{
str[pos] = '(';
_printParenthesis(pos+1, n1, open1, close1, n2, open2, close2, n3, open3+1, close3);
}
if(open2 < n2)
{
str[pos] = '{';
_printParenthesis(pos+1, n1, open1, close1, n2, open2+1, close2, n3, open3, close3);
}
if(open1 < n1)
{
str[pos] = '[';
_printParenthesis(pos+1, n1, open1+1, close1, n2, open2, close2, n3, open3, close3);
}
}
}
}
/* driver program to test above functions */
int main()
{
int n1, n2, n3;
n1 = 6;
n2 = 1;
n3 = 1;
printParenthesis(n1, n2, n3);
return 0;
}**
string[] CatalanNumber_GeneratingParanthesizedFactorsRecursive(string s)
{
if(s.Length == 1)
{
return new string[] {s};
}
if(s.Length == 2)
{
string r = "(" + s + ")";
return new string[] { r };
}
List<string> results = new List<string>();
for (int i = 1; i < s.Length; i++)
{
var r1 = this.CatalanNumber_GeneratingParanthesizedFactorsRecursive(
s.Substring(0, i));
var r2 = this.CatalanNumber_GeneratingParanthesizedFactorsRecursive(
s.Substring(i));
foreach(var s1 in r1)
{
foreach(var s2 in r2)
{
string r = "(" + s1 + s2 + ")";
results.Add(r);
}
}
}
return results.ToArray();
}
string[] CatalanNumber_GeneratingParanthesizedFactors(string s)
{
s.ThrowIfNullOrWhiteSpace("s");
if(s.Length == 1)
{
return new string[] {s};
}
var r = this.CatalanNumber_GeneratingParanthesizedFactorsRecursive(
s);
return r;
}
[TestMethod]
public void CatalanNumber_GeneratingParanthesizedFactorsTests()
{
var CatalanNumbers = new int[] { 1, 1, 2, 5, 14, 42, 132, 429,
1430, 4862, 16796 };
string input = "";
for (int i = 1; i <= 10; i++)
{
input += i;
var results2 = this.CatalanNumber_GeneratingParanthesizedFactors(input);
Assert.AreEqual(results2.Length, CatalanNumbers[input.Length-1]);
Debug.WriteLine("-----------------------------------------------");
foreach (string ss in results2)
{
Debug.WriteLine(ss);
}
}
string s = "a";
var r = this.CatalanNumber_GeneratingParanthesizedFactors(s);
Assert.AreEqual(r.Length, 1);
Assert.AreEqual(s, r[0]);
s = "ab";
r = this.CatalanNumber_GeneratingParanthesizedFactors(s);
Assert.AreEqual("(ab)", r[0]);
s = "abc";
r = this.CatalanNumber_GeneratingParanthesizedFactors(s);
string[] output = new string[] { "(a(bc))", "((ab)c)" };
Assert.AreEqual(2, r.Length);
foreach(var o in output)
{
Assert.AreEqual(1, r.Where(rs => (rs == o)).Count());
}
s = "abcd";
r = this.CatalanNumber_GeneratingParanthesizedFactors(s);
output = new string[] { "(a(b(cd)))", "(a((bc)d))", "((ab)(cd))", "(((ab)c)d)", "((a(bc))d)"};
Assert.AreEqual(5, r.Length);
foreach (var o in output)
{
Assert.AreEqual(1, r.Where(rs => (rs == o)).Count());
}
}
def catalan(n: Int): List[String] =
if (n == 0) List("")
else
for {
k <- (0 to n - 1).toList
first <- catalan(k)
rest <- catalan(n - 1 - k)
} yield "a" + first + "b" + rest
catalan(0) List()
catalan(1) List(ab)
catalan(2) List(abab, aabb)
catalan(3) List(ababab, abaabb, aabbab, aababb, aaabbb)
catalan(5).size 42