【问题标题】:Number of valid parenthesis有效括号数
【发布时间】:2017-02-01 21:36:58
【问题描述】:

我必须找出有效括号的数量。括号有两种类型[] ,()。有多少种方法可以使用[] ,() 的 X 和 Y 数来构造一个有效的序列。对于这个问题,我们认为([]) 是无效的方式,即() can't hold []. 有没有比递归更好的解决方案。

For Example X=1 and Y=1
[]()
()[]
[()]

【问题讨论】:

  • X=N, Y=0 的公式是2^(N-1),但我没有足够的咖啡来继续下去。我认为有一个合理的公式。
  • 您问“有没有比递归更好的解决方案?”也许如果你展示了你的递归解决方案,你就有可能将它变成一个 DP 程序。最难的部分(找出递归关系)应该已经完成​​了。
  • @stark 我认为这不对——对于X=N, Y=0(以及X=0, Y=N),答案是Nth Catalan 号码。请参阅“组合数学中的应用”下的 en.wikipedia.org/wiki/Catalan_number
  • @PaulHankin 我与加泰罗尼亚数字的不同之处在于(()()) 是否有效。如果是,那么我认为加泰罗尼亚数字是正确的,如果不是,那么 2^N。显然,我们都假设)( 是无效的。

标签: algorithm dynamic-programming catalan


【解决方案1】:

对于分组的自封闭圆括号和方括号的给定排列的任何给定组合,我们可以使用多集组合来确定排列的数量:

n + k - 1 choose k, where k is the smaller of the number of self-enclosed parenthetical groups and the total number of square brackets, and n is the larger of the two + 1.

方括号的排列数是第n个加泰罗尼亚数。

生成括号组的一种方法是分配越来越多的组,并计算 (X - 分配组的数量) 的每个分区的不同排列数乘以第 n 个部分的总和-加泰罗尼亚语。例如:

X = 4
Counts for each grouping:

1 group: Cat 3
2 groups: Cat 2 * 2 + 1 // partitions [2,0] * 2 and [1,1]
3 groups: 3 // partition [1,0,0] * 3
4 groups: 1 // partition [0,0,0,0]

我还没有想出避免分区的方法,并且有兴趣学习。

【讨论】:

  • 你好。我们说的或多或少是同一件事,不是吗?
  • @m69 是的,我想是的。
  • @m69 但我认为我们可能都遗漏了一些与括号的递归构造有关的东西。你从一个开始;然后将下一个放在 f(n-1) 的左侧或将每个可能性括起来。 1: (); 2: ()() (()); 3: ()()() (()()) ()(()) ((())) etc.我们如何使用该结构来概括括号和方括号的答案?
  • 我只能看到这导致了一种递归枚举所有可能性的算法,这是提问者试图避免的。 (顺便说一句,你错过了(())()
  • “避免递归”可能意味着“避免大量可笑的递归”。 20 的加泰罗尼亚数是 6,564,120,420,而 20 的分区数是 627,所以我会说递归分区的危害较小。
【解决方案2】:

因为方括号不能在圆括号内,所以在每次出现方括号之前,每个圆括号序列都必须是完整的(即开括号减去右括号的数量倒为零)。

  1      012    1      0  
()[(())()][[()()]((()))]()
10 121010   1010 123210 10

这实际上意味着方括号将圆括号分成单独的独立序列:

   1   0   1   2   1   0
...[...]...[...[...]...]...

圆括号的完整序列可以放在方括号之间的任何位置。

正如 Paul Hankin 所提到的,只有一种类型的括号的有效序列数由 Catalan Number 给出。这为您提供了方括号的有效序列数,以及要插入方括号之间某处的任意数量的圆括号的有效序列数。

不幸的是,找出圆括号可以通过什么方式分布到方括号之间的不同位置是一个分区问题,解决这个问题的逻辑方法是递归。因此,这种思路可能会导致一种算法,但不会导致一种避免递归的算法。

但是,查找分区所需的递归数远小于加泰罗尼亚数(例如 20 有 627 个分区,但 20 的加泰罗尼亚数是 6,564,120,420),因此这种方法比递归枚举每个有效序列要快得多.


这里有一个简单的例子来演示它是如何工作的:

X=2,Y=3

方括号的有效序列:

加泰罗尼亚语数(2) = 2

1. [ ] [ ]  
2. [ [ ] ]

圆括号的位置:

2 × X + 1 = 5

1[2]3[4]5
1[2[3]4]5

圆括号的分区:

p(Y) = 3

3
2,1
1,1,1

分区的排列:

分区:3(部分数量:1)
→ 5 = 5

3,0,0,0,0  0,3,0,0,0  0,0,3,0,0  0,0,0,3,0  0,0,0,0,3  

分区:2,1(部分数:2)
→ 5 × 4 = 20

2,1,0,0,0  2,0,1,0,0  2,0,0,1,0  2,0,0,0,1  
1,2,0,0,0  0,2,1,0,0  0,2,0,1,0  0,2,0,0,1  
1,0,2,0,0  0,1,2,0,0  0,0,2,1,0  0,0,2,0,1  
1,0,0,2,0  0,1,0,2,0  0,0,1,2,0  0,0,0,2,1  
1,0,0,0,2  0,1,0,0,2  0,0,1,0,2  0,0,0,1,2  

分区:1,1,1(部分数:3,相同:3)
→ (5 × 4 × 3) / (1 × 2 × 3) = 10

1,1,1,0,0  1,1,0,1,0  1,1,0,0,1  
1,0,1,1,0  1,0,1,0,1  1,0,0,1,1  
0,1,1,1,0  0,1,1,0,1  0,1,0,1,1  0,0,1,1,1  

圆括号的有效序列:

加泰罗尼亚语数(3) = 5

1. ()()()
2. ()(())
3. (())()
4. (()())
5. ((()))

加泰罗尼亚语数(2) = 2

1. ()()
2. (())

加泰罗尼亚语数(1) = 1

1. ()

加泰罗尼亚语数(0) = 1

1. 

每个分区的有效序列:

3,0,0,0,0  5 x 1 x 1 x 1 x 1  =  5
2,1,0,0,0  2 x 1 x 1 x 1 x 1  =  2
1,1,1,0,0  1 x 1 x 1 x 1 x 1  =  1

有效序列总数:

方括号:2
圆括号:75

 5 x 5 = 25  
20 x 2 = 40  
10 x 1 = 10  

总计:2 × 75 = 150

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 2018-12-26
    • 2019-10-06
    • 1970-01-01
    • 2014-01-11
    • 2019-03-17
    • 2013-11-07
    • 2011-03-11
    相关资源
    最近更新 更多