布尔括号化的递归memoized解决方案的运行时复杂性

时间:2016-05-08 05:20:45

标签: algorithm recursion runtime memoization boolean-expression

This是一个典型的算法问题。

DP解决方案确实是n ^ 3。

我在下面使用带有memoization的递归。

我需要详细解释下面代码的运行时间是什么?我对目前的答案不满意。有人可以帮忙吗?

 public static int countParenthesization(String expr, int begin, int end, boolean result, Map<String, Integer> lookup) {
    String lookupKey = begin + "-" + end + "-" + result;

    if (end - begin == 0) {
        String currenExpr = expr.charAt(begin) + "";
        int count = (currenExpr.equals("T") && result) || (currenExpr.equals("F") && !result) ? 1 : 0;
        lookup.put(lookupKey, count);
        return count;
    }

    if (lookup.containsKey(lookupKey)) {
        return lookup.get(lookupKey);
    }


    int count = 0;
    for (int i = begin + 1; i <= end; i = i + 2) {
        int leftBegin = begin;
        int leftEnd = i - 1;
        int rightBegin = i + 1;
        int rightEnd = end;

        switch (expr.charAt(i)) {
            case '|':
                if (result) {
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                } else {
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                }

                break;
            case '&':
                if (result) {
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                } else {
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                }

                break;
            case '^':
                if (result) {
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                } else {
                    count += countParenthesization(expr, leftBegin, leftEnd, true, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, true, lookup);
                    count += countParenthesization(expr, leftBegin, leftEnd, false, lookup)
                            * countParenthesization(expr, rightBegin, rightEnd, false, lookup);
                }

                break;
        }
    }

    lookup.put(lookupKey, count);

    //System.out.println(lookup);

    return count;
}

1 个答案:

答案 0 :(得分:1)

如上所述,您的代码为O(n ^ 4)。代码与DP解决方案基本相同,但是DP解决方案小心地在表中使用O(1)索引(一对(i,j)的整数),这段代码使用子串,构造其中需要O(n)时间,并且哈希表中的查找也需要O(n)时间。 [注意:这里的n指的是当前切片表达式字符串的长度,而不是哈希表的大小]。

您可以使用开始/结束索引并避免字符串切片(和哈希表查找)来补救增加的复杂性,就像在DP解决方案中一样。

具体地:

  • 该函数将采用开始/结束索引的额外参数int i, int j而不是预切片表达式。
  • 您的lookup哈希表的键将更改为元组<int i, int j, bool result>而不是字符串。
  • 您的代码根本不执行字符串切片。