Algorithm Google codejam亚太测试实践回合:括号顺序

Algorithm Google codejam亚太测试实践回合:括号顺序,algorithm,dynamic-programming,Algorithm,Dynamic Programming,我花了一天时间来解决这个问题,却找不到一个解决方案来传递这个大数据集 问题 n个圆括号序列由n“(“s和n”)”s组成 现在,我们有了所有有效的n个括号序列。按字典顺序查找第k个最小序列 例如,以下是按字典顺序排列的所有有效的3个括号序列: ((())) (()()) (())() ()(()) ()()() 给定n和k,编写一个算法,以字典顺序给出第k个最小序列 对于大型数据集:1≤ N≤ 100和1≤ K≤ 10^18这个问题可以通过使用动态规划来解决 设dp[n][m]=如果有

我花了一天时间来解决这个问题,却找不到一个解决方案来传递这个大数据集

问题

n个圆括号序列由n“(“s和n”)”s组成

现在,我们有了所有有效的n个括号序列。按字典顺序查找第k个最小序列

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

((()))

(()())

(())()

()(())

()()()
给定n和k,编写一个算法,以字典顺序给出第k个最小序列


对于大型数据集:
1≤ N≤ 100和
1≤ K≤ 10^18

这个问题可以通过使用动态规划来解决

  • dp[n][m]
    =如果有
    n
    开括号和
    m
    闭括号,则可以创建的有效括号数
  • 基本情况:
    dp[0][a]=1(a>=0)
  • 使用基本大小写填写矩阵:
    dp[n][m]=dp[n-1][m]+(n
然后,我们可以慢慢地构建第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
    
    请注意,按字典顺序,开括号比闭括号小,所以我们总是先添加开括号


这个问题可以通过使用动态规划来解决

  • dp[n][m]
    =如果有
    n
    开括号和
    m
    闭括号,则可以创建的有效括号数
  • 基本情况:
    dp[0][a]=1(a>=0)
  • 使用基本大小写填写矩阵:
    dp[n][m]=dp[n-1][m]+(n
然后,我们可以慢慢地构建第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
    
    请注意,按字典顺序,开括号比闭括号小,所以我们总是先添加开括号


S=从n(和n)开始的任何有效括号序列
。 现在,任何有效的序列S都可以写成
S=X+Y
where

  • X=有效前缀
    即,如果在任何时间点从左到右遍历X,
    numberof'('>=numberof')”
  • Y=有效后缀
    即,如果在任何时间点从右向左遍历Y,
    numberoff'('ncp),因此可能没有有效后缀*/
    dp[nop][ncp]=i1+i2;
    }
    返回dp[nop][ncp];
    }`
    
    例如,n=3,即3
    和3
    现在,从一开始,X=empty_string
,因此

dp[3][3]
=使用3
和3

=3
和3
)中有效后缀的数量
Y

S=n(和n)中的任何有效括号序列
。 现在,任何有效的序列S都可以写成
S=X+Y
where

  • X=有效前缀
    即,如果在任何时间点从左到右遍历X,
    numberof'('>=numberof')”
  • Y=有效后缀
    即,如果在任何时间点从右向左遍历Y,
    numberoff'('ncp),因此可能没有有效后缀*/
    dp[nop][ncp]=i1+i2;
    }
    返回dp[nop][ncp];
    }`
    
    例如,n=3,即3
    和3
    现在,从一开始,X=empty_string
    ,因此

    dp[3][3]
    =使用3
    和3

    =来自3
    和3
    )的有效后缀
    Y
    的数量

    那么你的问题是什么?@WimOmbelets我猜,解决上述问题的算法是什么?WimOmbelets我猜,解决上述问题的算法填充有效括号的基本情况是什么?谢谢你的算法。我运行了它,它是正确的。但是dp[n][m]的含义是什么(如果我们有n-开括号的数量和m-闭括号的数量,那么可以创建有效括号的数量)这让我很困惑。如果n!=m,我们如何才能得到有效括号?我不太理解dp[n][m]的含义@Danny您可以理解,在放下一些开括号和一些闭括号之后,从左括号中,您可以从这些括号中创建多少不同的有效配置。这就是为什么基本情况是dp[0][a],这意味着当你只有右括号时,你唯一能做的就是把它们都放下来。@Phamtrong这对我来说是有意义的。谢谢!@user2761431假设n=4,我们已经创建了这样的smt(()(”,因此,我们唯一能做的就是把它们都放在3个右括号中,这使得基本情况dp[0][3]=1:)填充有效括号数的基本情况是什么?谢谢你的算法。我运行了它,它是正确的。但是dp[n][m]的含义(如果我们有n-开括号数和m-闭括号数,则可以创建有效括号数)我不太明白dp[n][m]的意思。@Danny你可以理解,在放下一些开括号和闭括号后,从左括号中,你可以从这些括号中创建多少不同的有效配置。这就是为什么基本情况是dp[0][a],这意味着当你只有右括号时,你唯一能做的就是把它们都放下来。@Phamtrong这对我来说是有意义的。谢谢!@user2761431假设n=4,我们已经创建了这样的smt(()(”,因此,我们唯一能做的就是把它们都放在3个右括号中,这使得基本情况dp[0][3]=1:)
    `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];
    }`