【问题标题】:How many valid parenthesis combinations?有多少个有效的括号组合?
【发布时间】:2013-08-04 17:13:46
【问题描述】:

我们有:

  • n1{} 括号的数量,

  • n2() 括号的数量,

  • n3[] 括号的数量,

这些括号有多少种不同的有效组合?

我的想法:我用java写了一个蛮力代码(下面有)并计算了所有可能的组合,我知道这是可能的最糟糕的解决方案,

(代码是针对一般情况,我们可以有不同类型的括号)

任何数学方法?

注 1:有效组合通常定义,例如{{()}}:有效,{(}){}:无效

注 2:假设我们有 2 对 {} ,1 对 () 和 1 对 [],有效组合的数量为 168 和所有可能的数量(有效和无效) 组合为 840

static void paranthesis_combination(char[] open , char[] close , int[] arr){
    int l = 0;
    for (int i = 0 ; i < arr.length ; i++)
        l += arr[i];
    l *= 2;
    paranthesis_combination_sub(open , close , arr , new int[arr.length]  , new int[arr.length], new StringBuilder(), l);
    System.out.println(paran_count + " : " + valid_paran_count);
    return;
}


static void paranthesis_combination_sub(char[] open , char[] close, int[] arr , int[] open_so_far , int[] close_so_far, StringBuilder strbld , int l){
    if (strbld.length() == l && valid_paran(open , close , strbld)){
        System.out.println(new String(strbld));
        valid_paran_count++;
        return;
    }
    for (int i = 0 ; i < open.length ; i++){
        if (open_so_far[i] < arr[i]){
            strbld.append(open[i]);
            open_so_far[i]++;
            paranthesis_combination_sub(open , close, arr , open_so_far , close_so_far, strbld , l);
            open_so_far[i]--;
            strbld.deleteCharAt(strbld.length() -1 );
        }
    }
    for (int i = 0 ; i < open.length ; i++){
        if (close_so_far[i] < open_so_far[i]){
            strbld.append(close[i]);
            close_so_far[i]++;
            paranthesis_combination_sub(open , close, arr , open_so_far , close_so_far, strbld , l);
            close_so_far[i]--;
            strbld.deleteCharAt(strbld.length() -1 );
        }
    }
    return;
}

【问题讨论】:

  • 如何定义一个有效的组合?根据解析规则,这个问题可能有很多不同的答案。
  • 问题现已编辑
  • 查找加泰罗尼亚数字。 ({}) 有效吗?
  • 你知道 StackExchange 得到了Math section?我相信他们可能更擅长数学答案:-p

标签: math recursion combinations discrete-mathematics


【解决方案1】:

Cn 是第 n 个加泰罗尼亚数字 C(2n,n)/(n+1),并给出仅使用 () 的长度为 2n 的有效字符串的数量。因此,如果我们将所有[]{} 更改为(),就会有Cn1+n2+n3 方式。然后有C(n1+n2+n3,n1)方法将n1()改回{}C(n2+n3,n3)方法将剩余的()改成[]。综上所述,有C(2n1+2n2+2n3,n1+n2+n3)C(n1+n2+n3,n1)C(n2+n3,n3)/(n1+n2+n3+1) 方式。

作为检查,当n1=2n2=n3=1 时,我们有C(8,4)C(4,2)C(2,1)/5=168

【讨论】:

  • 干得好!加泰罗尼亚数字一开始就提到了,但我懒得去查了:)
【解决方案2】:

一般来说,无限。但是我假设,您的意思是找到有多少组合提供了有限的字符串长度。为简单起见,我们假设极限是偶数。然后,让我们创建一个初始字符串:

(((...()...))) 长度等于限制。

然后,我们可以用 [] 或 {} 括号切换 () 对的任何实例。但是,如果我们更改左大括号,那么我们应该更改匹配的右大括号。因此,我们只能查看左大括号或成对。对于每个括号对,我们有 4 个选项:

  • 保持不变

  • 将其更改为 []

  • 将其更改为 {}

  • 删除它

因此,对于 (l/2) 个对象中的每一个,我们从四个标签中选择一个,给出: 4^(l/2) 个可能性。

编辑:这假定只有“同心”括号字符串(彼此包含),正如您在编辑中所建议的那样。然而,直观地说,有效的组合也是:()[]{} - 此解决方案没有考虑到这一点。

【讨论】:

  • 正如我所说,我们对每一对都有特定的数字(n1 of {} 括号)所以它不能是无限的,我假设 ()[]{} 是有效的!
  • 抱歉,您对数字的看法是正确的。我会努力改进我的答案。
  • 我添加了一个示例输入和输出
  • 我现在放弃了:P
  • 将所有内容更改为 () 最终是一个很好的开始方式。谢谢你的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 2022-01-25
相关资源
最近更新 更多