跳转至

OJ2-3_游戏_括号匹配

思路

夹带一点私货,这个问题是小编觉得非常有意思的一个问题。小编了解到这个题大家都会用两个栈解决,但其实只要作一个转换,就可以一个栈都不用。

两个栈的解法

用两个栈一个装A球一个装C球,若遇到A/C球则把它们压入相应的栈中,若遇到B球则优先弹出A球进行匹配,若A栈为空则弹出C球进行匹配,若C栈也为空则这是一个不合规序列,可以直接结束程序。

若对所有球都执行完操作还是没有结束程序,则将所有在栈里的A球和C球排列出来,若还剩n个球,则将后n个C球变成B球(若C球个数小于n直接判断为不合规),其他C球拿掉,再进行匹配,若匹配成功则合规,否则不合规。

不用栈的解法

私货来了!

先考虑这样一个问题:如果这个题没有C球,那么是不是就变得好解了?

只需要从头扫一遍,在任意位置前面的A球都不少于B球的数目,且AB球数目相等就行。

那么我们能不能把C球按照一种规则转化成A球或者B球或者拿掉,然后再进行判断呢?

可以的!

概念:转化

为了更好的说明,先引入一个概念——转化。

比如我们有序列AACCC,则其变为AABB就是一种转化。

一个序列合规当且仅当它的一种转化合规。

接下来我们引入两个引理:

引理1

若一个序列的一种转化

……C……C……变成……B……A……

合规,则其另一种转化

……C……C……变成……A……B……

合规。

证明:

若……B……A……合规,则一定存在A‘与B配对,B’与A配对,如下

……A‘……B……A……B'……

那么另一种转化

……A‘……A……B……B'……

也可以如此匹配

引理2

若一个序列的一种转化

……C……C……变成……拿掉……拿掉……

合规,则其另一种转化

……C……C……变成……A……B……

合规。

证明

若……拿掉……拿掉……合规,则我们可以让两个C相互匹配,如下

……A……B……

定理

一个序列合规当且仅当其按照这样一种转化完仍合规:将前一半C球转化成A球,后一半转化成B球,若C球总共为奇数个则拿掉最中间的一个C球。

充分性:

易得

必要性:

若这个序列合规,则其一定存在一个转化合规

将这个转化的所有拿掉的C球按照引理2产生A,B球,直到最后只剩1个或者不剩C球了

再将所有转化得到的A,B球应用引理1交换次序,直到所有转化得到的A球在所有转化得到的B球前面

由此这个操作完之后的序列也合规

所以我们只需要应用此定理将其进行转化就可以转化为只有A,B球的问题。

伪代码

i=0
j=n-1

//应用定理转化C球
while True:
    keep i++ until find array[i]=C or i=n
    keep j-- until find array[j]=C or j=-1
    array[i]=A
    array[j]=C
    if i==j:
        pick out array[i]
        break
    if i==n:
        break

//计算只含有A,B球的序列
judge array with only A and B
本站总访问量

评论