Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算非平凡问题的时间复杂度_Java_Algorithm_Recursion_Time Complexity_Catalan - Fatal编程技术网

Java 计算非平凡问题的时间复杂度

Java 计算非平凡问题的时间复杂度,java,algorithm,recursion,time-complexity,catalan,Java,Algorithm,Recursion,Time Complexity,Catalan,我在计算下面所示程序的时间复杂度时遇到困难。这是一个生成有效括号的简单程序,如“(())”“(())”等。但是,我真的不知道如何估计这类问题的时间复杂度 如果您能在这里分享一些您觉得有用的技术,我们将不胜感激。如果您能分析我链接的程序(例如:)将是最好的选择 我的目标是: 估计非平凡程序的时间复杂度。通常是一个递归程序,有一些修剪 我在寻找一个快速的估计解决方案,而不是严格的数学证明 先谢谢你 有关守则: public ArrayList<String> generateParent

我在计算下面所示程序的时间复杂度时遇到困难。这是一个生成有效括号的简单程序,如“(())”“(())”等。但是,我真的不知道如何估计这类问题的时间复杂度

如果您能在这里分享一些您觉得有用的技术,我们将不胜感激。如果您能分析我链接的程序(例如:)将是最好的选择

我的目标是:

  • 估计非平凡程序的时间复杂度。通常是一个递归程序,有一些修剪

  • 我在寻找一个快速的估计解决方案,而不是严格的数学证明

  • 先谢谢你

    有关守则:

    public ArrayList<String> generateParenthesis(int n) {
        ArrayList<String> res = new ArrayList<String>();
        String oneSolu = "";
    
        Generate(n, n, res, oneSolu);
    
        return res;
    }
    
    private void Generate(int l, int r, ArrayList<String> res, String oneSolu) {
        if (l==0 && r==0) {
            res.add(oneSolu);
            return ;
        }
    
        //add left
        if (l > 0) {
            String t = oneSolu;
            t += "(";
            Generate(l-1, r, res, t);
        }
    
        if (r>l) {
            String t = oneSolu;
            t += ")";
            Generate(l, r-1, res, t);
        }
    }
    
    public ArrayList generateParenthesis(int n){
    ArrayList res=新的ArrayList();
    字符串oneSolu=“”;
    生成(n,n,res,oneSolu);
    返回res;
    }
    私有void生成(int l、int r、ArrayList res、字符串oneSolu){
    如果(l==0&&r==0){
    res.add(oneSolu);
    返回;
    }
    //左加
    如果(l>0){
    字符串t=oneSolu;
    t+=“(”;
    生成(l-1,r,res,t);
    }
    如果(r>l){
    字符串t=oneSolu;
    t+=”;
    生成(l,r-1,res,t);
    }
    }
    
    使用n对生成的有效括号数是n个加泰罗尼亚数,定义为
    2nCn/(n+1)
    ,但如果需要更简化的边界,则为
    O(4^n)
    。更一般地说,任何递归函数都是由其最大分支因子和深度作为上界的,如
    O(b^d)
    如果在每个级别上所做的工作是
    O(1)
    ,那么在这种情况下,深度=2N,分支因子大约为2,因此
    T(n)=2^(2N)=4^n。我必须承认,您的特定用例似乎特别困难,所以不要对自己太苛刻

  • 估计非平凡程序的时间复杂度。通常是递归的 有一些修剪的程序

  • 我在寻找一个快速的估计解决方案,而不是一个严格的数学模型 证明

  • 当我分析运行时,我可以给你我的正常思维过程。对于这种特殊情况,它不会有太大的帮助,但在一般情况下肯定会有帮助(如果您稍后在分析其他程序时遇到问题)

    我不能保证不使用严格的数学;如果我真的想确定一个界限,我倾向于默认它。对于松散的边界,这些东西通常足够简单,但它不是一个大问题


    首先,我通常会考虑两件主要的事情

    1)我至少可以写下重现期吗?

    许多人都熟悉一些复发(比如T(n)=T(n-1)+T(n-2)),而有些复发已经被广泛研究过(比如任何可以用master方法解决的问题)。如果一个程序属于这一类,认为自己相当幸运。

    在你的特殊情况下,复发似乎是

    如果R>L
    T(L,R)=T(L-1,R),否则,基本情况下
    T(0,R)=R

    这不是最好的开始

    2)分析使用特定参数调用特定函数的次数

    这种方法通常在动态规划中更有用,在动态规划中存储过去的结果以节省计算量,但它也是皮带中的另一种工具。也就是说,如果您无法计算使用特定参数调用函数的次数,那么这不是一个选项

    然而,在这种情况下,这种方法在数学上很难实现。基本问题是使用特定的
    l
    r
    调用
    Generate()
    的次数完全取决于
    oneSolu
    的可能值。(ArrayList是一个累加器,因此不必担心)

    在我们的例子中,我们碰巧知道字符串的长度(因为第一次调用的长度是
    l=r=n
    ,并且每个递归调用正好将两个调用中的一个减少了1),我们还可以证明这一点

  • 对于传入的
    oneSolu
    的每个值,我们可以保证每个前缀的
    s)都比
    s多
  • 这一特定长度的每一个这样的字符串都包含在内
  • 我很确定这个值是可以找到的,但是1)数学很快就会变得难看,2)即使你走了那么远,你也必须用一个双重求和来计算它。不实用,甚至到目前为止,数学处理的比你想要的还要多


    现在来看看获得上界的粗糙方法。这是一种“快速”的方法,但是它没有考虑任何类型的修剪,所以如果你想要一个紧凑的边界,它可能是非常无用的。它已经被贴出来了,但我还是要加上它,这样这个答案就可以自己总结一切了

    3)将最大深度乘以最大分支因子。


    正如@Vikramhat已经指出的,你的分支因子是2,最大深度是2n,所以你看到的是一个22n=4n的(非常非常)松散的边界,正如@KarolyHorvath在评论中指出的,每个节点的功是线性的,因此我们得到了一个O(n4n)运行时间。

    为什么在不使用的情况下,左右两边的时间都过去了?我忘了把它拿走..从来没有mind@RobinGreen是的,OP给出的代码是用Java编写的,但听起来OP所要求的是语言不可知的。@DennisMeng好的,我想大多数计算机科学家应该能够阅读Java代码。这是一个公平的观点。链接到加泰罗尼亚数字维基百科我不太确定这是否正确。是的,匹配括号任务是加泰罗尼亚数字有用性的经典例子。但是,只有假设每个解决方案/节点都可以使用O(1)生成时,此分析和深度分析才是正确的。我认为这里的字符串创建增加了一个O(N)乘数。“让我想想。”卡洛利霍瓦特说