Algorithm 布尔括号递归记忆解的运行时复杂性

Algorithm 布尔括号递归记忆解的运行时复杂性,algorithm,recursion,runtime,memoization,boolean-expression,Algorithm,Recursion,Runtime,Memoization,Boolean Expression,是一个经典的算法问题 DP解决方案实际上是n^3 我在下面的记忆中使用递归 我需要一些关于下面代码的运行时的详细解释?我对目前的答案不满意。有人能帮忙吗 public static int countParenthesization(String expr, int begin, int end, boolean result, Map<String, Integer> lookup) { String lookupKey = begin + "-" + end + "-"

是一个经典的算法问题

DP解决方案实际上是n^3

我在下面的记忆中使用递归


我需要一些关于下面代码的运行时的详细解释?我对目前的答案不满意。有人能帮忙吗

 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;
}
公共静态int count圆括号(字符串表达式、int开始、int结束、布尔结果、映射查找){
字符串查找键=开始+“-”+结束+“-”+结果;
如果(结束-开始==0){
字符串currenExpr=expr.charAt(begin)+“”;
整数计数=(当前表达式等于(“T”)和结果)| |(当前表达式等于(“F”)和结果)?1:0;
lookup.put(lookupKey,count);
返回计数;
}
if(lookup.containsKey(lookupKey)){
返回lookup.get(lookupKey);
}
整数计数=0;
对于(inti=begin+1;i,您的代码是O(n^4)。代码本质上与DP解决方案相同,但DP解决方案小心地在表中使用O(1)索引(一对(i,j)int),此代码使用一个子字符串,其构造需要O(n)时间,而哈希表中的查找也需要O(n)时间。[注意:这里的n是指当前切片表达式字符串的长度,而不是哈希表的大小]

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

具体地说:

  • 该函数将接受开始/结束索引的额外参数
    inti,intj
    ,而不是预切片表达式
  • 您的
    查找
    哈希表的键将更改为元组
    ,而不是字符串
  • 您的代码将根本不执行字符串切片

Hi@PaulHankin,谢谢你的回答。你说运行时间是O(n^4)。你能详细说明一下它是怎样的O(n^4)吗?想象一下,您不知道一个DP解决方案的运行时间是n^3。换句话说,当您有三个循环时,很容易得出n^3。但是当您有一个带有3个带记忆的递归调用的循环时,最好的分析方法是什么?给定一个表达式,假设子结果已经计算并散列,然后分析复杂性(在我在答案中建议的优化之后是O(n^2)或O(n)),然后注意,表达式的每个子串(在最坏的情况下)都是最终计算出来的,并且有O(n^2)个子串,所以总体复杂度是O(n^4)。本质上,你必须像在数学证明中一样进行论证,而不是进行简单的基于循环的复杂度分析。当然,这一评论是非正式的、具有启发性的,而不是仔细的、数学上精确的。这一论证本质上是在自上而下的递归记忆解决方案和自下而上的DP解决方案之间构建等价关系如果忽略了<代码> > 和<代码>和<代码>,并且只考虑<代码> ^ /代码>——因为自顶向下的解决方案在代码< >代码< >代码>和<代码>和代码>情况下可以快捷工作。但是最坏情况的行为仍然是相同的。我不满意当前的答案。有人可以帮助说明运行时是什么吗?上面的代码是什么?