数列与规律
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
探索规律的奥秘——括号序列
摘要
本文探讨了在一定限制条件下“合法括号序列”的数量。使用几种不同的方法,先有条理地分析、探索出递推的规律,进而推导得出公式。
引入
定义“括号序列”为一串由“(”和“)”组成的序列。定义“合法的括号序列”为一个可以将“(”和“)”配对,从而满足以下条件的括号序列:
1、“(”和“)”数量相等。
2、两对括号之间要么是包含关系(形如“(())”),要么互不相交(形如“()()”).
不难证明,一个合法的括号序列只有一种合法的配对方法。
接着,我们把一个括号序列写成“分行”形式:例如把
()(()((())()))(())写成:()( )( )
()( ) ()
( )()
()
则我们定义“合法括号序列的深度”为其“分行”形式所占用的行数(例如以上序列的“深度”就是4)。
当然,也有更严谨的定义方法:“深度”就是原序列任意前缀中“(”和“)”数量之差的最大值。也就是说,设原序列为A,从A的开头开始从左往右选取连续的一些字符,就能“截”出一串新的括号序列V(不一定合法),并求得V序列中“(”与“)”数量之差。通过这种方式所能得到的最大的差,就是A序列的深度。为什么?因为在“分行形式”中,从开头往右看,看到一个“(”就代表着“以后的字符向下进一行”,看到“)”就代表着“以后的字符向上回退一行”,两者相抵,所以把两者数量相减,就能得到V序列最后一个括号的深度。这样的话,最深的括号的深度——也就是所得差的最大值——即为A序列的深度,也就是其分行形式占用的行数。
因此,以上两种对“深度”的定义等价。
问题来了:给定正整数N和K,找出一种高效的算法,用以求包含N对括号且深度为K的合法括号序列数量。
一种简单但是错误的算法
显而易见,解决此问题的高效方法是递推。
但是,每次从哪几个数递推到那几个数?递推几次?按照什么规律递推?
不难想到的一种方法是:
首先,死算出N=1情况下的结果:
当K=1,所求结果为1。
对应的序列有:()
当K≠1,所求结果为0。
于是,把N=1时的所有序列:()
在任意合法位置添加一对括号:()() (()) 新添加的用红色标记。
就不重不漏地得到了N=2时的所有序列。
故当N=2时:
当K=1时,所求结果为1。
对应的序列有:()()
当K=2时,所求结果为1。
对应的序列有:(())
当K≠1且K≠2时,所求结果为0。
于是,把N=2时的所有序列: ()() (())
在任意合法位置添加一对括号:()()() ((()))
(()())(())()
就不重不漏地得到了N=3时的所有序列?
这下,我们发现了问题!
图中标出的三对序列被重复计算了!所以,以上算法——虽然它可以通过改进来变得很高效——归根结底是错误的!
让我们总结一下错因:
在以上方法中,我们是如何得到某一个序列的?从最基本的“()”开始,我们不断在任意合法位置添加一对括号,最后得到所有序列。但是,以这种方式,我们可以用多种顺序添加括号,来得到同一个序列,因而导致重复计算。也就是说,导致错误的是,一个序列,有多种得到它的方法!
所以,我们要适当调整添加括号的顺序,使得每一个序列有且仅有一种得到它的方法——至少在“不断添加括号”的思路下是如此。
一种正确但略显复杂的算法
如何调整顺序呢?不难想到,可以“从左往右”添加括号。
位于同一个合法括号序列中的两对括号A和B,如果A的左括号在B的左括号左边,就说A在B左边;反之,就说A在B右边。
举个例子:对括号序列()(()((())()))(()),在“从左往右添加”的方法下,是这样得到它的:(新添加的用红色标出。)
1、()
2、 ()()
3、 ()(())
4、 ()(()())
5、 ()(()(()))
6、 ()(()((())))
7、 ()(()((())()))
8、()(()((())()))()
9、()(()((())()))(())
这时,我们发现,在添加的过程中,出现了两种现象。第一,每次,把当前序列中红色左括号右边(不包括它自己)的部分截取出来,那么其中一定全是“)”;第二,每次红色的一对括号的左右两半都是紧挨着的。
为什么?道理并不难。
第一:因为我们“从左往右”添加括号,所以每次添加的一对括号一定是“最右边”的一对。又因为我们用左括号位置来判别两对括号之间的“左右”关系,所以新添加的左括号一定是最右边的左括号,进而,它的右边没有左括号,就全是右括号。
第二:因为红色左括号的右边全是右括号,所以如果红色右括号不是紧挨其右,红色的一对括号之间就有且仅有一些黑色右括号。这样当前序列就不合法了,因为红色的一对括号与某些黑色括号部分相交。因此,红色的左右括号必然紧邻。
事实上,只要简单地遵循以上两个原则添加红括号,就能做到“从左往右”添加。
让我们总结一下:1.我们从空序列“”开始;
2.每次,我们在末尾连续的右括号之间或者在紧挨其左处;
3.添加一对左右紧邻的新括号;
4.就可以不重不漏地得到任意的合法括号序列。
这样,我们记为包含i 对括号、深度为j 、且末尾连续的“)”数量为p 的合法括号序列数量。那么,对自然数i,j,p,(j ≥p )我们可以得到递推式:
⎪⎪⎪⎪⎪⎪⎩⎪⎪⎪⎪⎪⎪⎨⎧>=>++==>≠>>>>≤=====>>===-------=-∑)1,1()1,1(1),0,0,1()0,0(0)0(1)0,0(0)1,1(0)1(11,1,11,,1,,11,,1,,i j p i A A A j p i j p j p i A j p i p j i jp i jp i ijp A p j i j j i j j i j
p m m j i p
j
解释一下其意思:
对于第1行:当i=1,j=1,p=1时,易知只有一个合法序列: ()
对于第2 、3、5行:这两种情况不存在合法序列。
对于第4行:当i=j=p=0,唯一的合法序列是空序列“”。
对于第6行:首先需要明确的是,p 不仅是序列末尾连续的“)”数量,也是序列中最右边一对括号的深度。i >1表示括号数量不止一个;p>0,j>0是序列合法性的保证。p ≠j 表示:最右边一对括号的深度不等于序列深度,也就是说,p j A ,,i