【问题标题】:Time complexity for combination of parentheses括号组合的时间复杂度
【发布时间】:2016-05-23 08:19:06
【问题描述】:

我尝试做经典问题来实现一个算法来打印 n 对括号的所有有效组合。

我找到了这个程序(运行良好):

public static void addParen(ArrayList<String> list, int leftRem, int rightRem, char[] str, int count) {
    if (leftRem < 0 || rightRem < leftRem) return; // invalid state

    if (leftRem == 0 && rightRem == 0) { /* all out of left and right parentheses */
        String s = String.copyValueOf(str);
        list.add(s);
    } else {
        if (leftRem > 0) { // try a left paren, if there are some available
            str[count] = '(';
            addParen(list, leftRem - 1, rightRem, str, count + 1);
        }
        if (rightRem > leftRem) { // try a right paren, if there’s a matching left
            str[count] = ')';
            addParen(list, leftRem, rightRem - 1, str, count + 1);
        }
    }
}

public static ArrayList<String> generateParens(int count) {
    char[] str = new char[count*2];
    ArrayList<String> list = new ArrayList<String>();
    addParen(list, count, count, str, 0);
    return list;
}

据我了解,我们的想法是尽可能添加左括号。对于右括号,只有当右括号的剩余数量大于左括号时,我们才会添加它。如果我们使用了所有的左右括号,我们会将新的组合添加到结果中。我们可以确定不会有任何重复的构造字符串。

对我来说,这种递归就像我们处理一棵树并且我们进行前序遍历例如:我们每次都可能去一个左节点,如果不是我们去右边,然后我们尝试在这一步之后向左走。如果我们不能,我们“回来”并向右走,然后我们重复遍历。在我看来,这里的想法完全一样。

所以,天真地,我认为时间复杂度将类似于 O(log(n))、O(n.log(n)) 或类似的对数。但是,当我试图搜索时,我发现了一个叫做“加泰罗尼亚语数”的东西,我们可以用它来计算括号组合的数量......(https://anonymouscoders.wordpress.com/2015/07/20/its-all-about-catalan/

您认为时间复杂度是多少?我们可以在这里应用主定理吗?

【问题讨论】:

    标签: algorithm time-complexity combinations parentheses catalan


    【解决方案1】:

    此代码的复杂度为 O(n * Cat(n)),其中 Cat(n) 是第 n 个加泰罗尼亚数。有 Cat(n) 个可能的有效字符串,它们是括号的有效组合(请参阅https://en.wikipedia.org/wiki/Catalan_number),并为每个字符串创建一个长度为 n 的字符串。

    由于 Cat(n) = choose(2n, n) / (n + 1),O(n * Cat(n)) = O(choose(2n, n)) = O(4^n / sqrt( n))(见https://en.wikipedia.org/wiki/Central_binomial_coefficient)。

    你的推理有两个主要缺陷。首先是搜索树不平衡:关闭右大括号时搜索的树与添加另一个左大括号时搜索的树大小不同,因此计算复杂度的更常用方法不起作用.第二个错误是,即使您假设树是平衡的,搜索树的 高度 也会是 n,并且找到的叶子数为 O(2^n)。这与二叉搜索树的分析不同,二叉搜索树中通常有 n 个事物,高度为 O(log n)。

    我认为这里没有任何标准的方法来计算时间复杂度——最终,当你计算有效的括号字符串时,你将重现类似数学的东西——而主定理不会为您提供动力。

    但是这里有一个有用的见解:如果一个程序生成 f(n) 个东西,以及每个 if c(n) 生成的成本,那么这个程序的复杂度不能比 O(c(n)f (n))。这里,f(n) = Cat(n) 和 c(n) = 2n,因此即使分析代码很困难,您也可以快速获得复杂度的下限。这个技巧会立即让你放弃复杂度为 O(log n) 或 O(n log n) 的想法。

    【讨论】:

    • 如果你熟悉加泰罗尼亚数字,你能帮我解决山脉问题(你的第一个链接中的数字)。作为一个问题听起来真的很酷,我想解决它,这是我的问题:stackoverflow.com/questions/37389354/…
    • 在旁注中,麻省理工学院教授 Richard Stanley 收集了超过 200 个问题的列表,这些问题的答案是加泰罗尼亚语数字:www-math.mit.edu/~rstan/ec
    猜你喜欢
    • 2021-08-07
    • 2018-01-14
    • 2017-07-07
    • 2023-02-22
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多