Google codejam APAC测试练习轮:圆括号顺序

时间:2014-09-22 09:56:58

标签: algorithm dynamic-programming

我花了一天时间解决this problem并且无法找到传递大型数据集的解决方案。

问题

n括号序列由n"(" s和n")" s组成。

现在,我们拥有所有有效的n个括号序列。找到词典顺序中的第k个最小序列。

例如,以下是按字典顺序排列的所有有效3个括号序列:

((()))

(()())

(())()

()(())

()()()

给定n和k,编写一个算法,以词典顺序给出第k个最小的序列。

对于大型数据集:1 ≤ n ≤ 1001 ≤ k ≤ 10^18

2 个答案:

答案 0 :(得分:5)

使用动态编程

可以解决此问题
  • 如果我们有dp[n][m]左括号和n近括号,则m =可以创建的有效括号数。
  • 基本情况:
    dp[0][a] = 1 (a >=0)
  • 使用基本情况填写矩阵:
    dp[n][m] = dp[n - 1][m] + (n < m ? dp[n][m - 1]:0 );

然后,我们可以慢慢建立第k个括号。

  • a = n左括号 b = n近括号开头,当前结果为空

    while(k is not 0):
         If number dp[a][b] >= k: 
                If (dp[a - 1][b] >= k) is true:
                   * Append an open bracket '(' to the current result
                   * Decrease a 
                Else:
                   //k is the number of previous smaller lexicographical parentheses
                   * Adjust value of k: `k -= dp[a -1][b]`,
                   * Append a close bracket ')' 
                   * Decrease b
         Else k is invalid
    

    请注意,开放式括号在字典顺序中小于近括号,所以我们总是先尝试添加开括号。

答案 1 :(得分:0)

S= any valid sequence of parentheses from n( and n)。 现在任何有效的序列S都可以写成S=X+Y其中

  • X=valid prefix,即如果在任何时间点从左到右遍历X,numberof'(' >= numberof')'
  • Y=valid suffix,即如果在任何时间点从右到左遍历Y,numberof'(' <= numberof')'

对于任何SXY都是可能的。

我们的示例:()(())

`()(())` =`empty_string + ()(())` 
         = `( + )(())`
         = `() + (())` 
         = `()( + ())` 
         = `()(( + ))` 
         = `()(() + )`
         = `()(()) + empty_string`

请注意,X=empty_string时,来自n S和n (的有效)的数量=来自n的有效后缀Y的数量(和n )

现在,算法是这样的: 我们将从X= empty_string开始,递归X增长到X=S。在任何时候,我们都有两种增长X的选项,可以追加&#39;(&#39;或追加&#39;)&#39;

dp[a][b]= number of valid suffixes using a '(' and b ')' given X

nop=num_open_parenthesis_left ncp=num_closed_parenthesis_left

`calculate(nop,ncp)
{
  if dp[nop][ncp] is not known
  {
    i1=calculate(nop-1,ncp); // Case 1: X= X + "("
    i2=((nop<ncp)?calculate(nop,ncp-1):0);
/*Case 2: X=X+ ")" if nop>=ncp, then after exhausting 1 ')' nop>ncp, therefore there can be no valid suffix*/
    dp[nop][ncp]=i1+i2;
  }
   return dp[nop][ncp];
}`

让我们举个例子,n = 3,即3 (和3 ) 现在开始X=empty_string,因此

dp[3][3] =使用3 S和3 (的有效序列)的数量  =来自3 Y和3 (的有效后缀)的数量