Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/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
Recursion 难以理解大的Oh复杂性_Recursion_Big O_Time Complexity - Fatal编程技术网

Recursion 难以理解大的Oh复杂性

Recursion 难以理解大的Oh复杂性,recursion,big-o,time-complexity,Recursion,Big O,Time Complexity,这不是家庭作业,而是课堂上的练习题。我知道没有解决办法。我想看看我做得对不对。另外,我如何发现时间复杂性?下面是我在这个问题的底部的解决方案 确定以下程序片段的大复杂性 (一) void sum1(int n){ sum1=0; 对于(i=1;i)让我们考虑一个你已经解决的问题: void sum2(int n){ sum2 = 0; for(i=1; i<=n; i++) for (j=1; j<=i; j++) sum

这不是家庭作业,而是课堂上的练习题。我知道没有解决办法。我想看看我做得对不对。另外,我如何发现时间复杂性?下面是我在这个问题的底部的解决方案

确定以下程序片段的大复杂性

(一)

void sum1(int n){
sum1=0;

对于(i=1;i)让我们考虑一个你已经解决的问题:

void sum2(int n){   
    sum2 = 0;
    for(i=1; i<=n; i++)
        for (j=1; j<=i; j++)
            sum2++;
}

让我们考虑3)

在考虑递归之前,让我们先看看一般情况下的成本(注释
R
):

然后按照输入大小的一半进行两次递归-因此对于
A
我们现在得到:

A(1) = 0
A(n) = n(n+1)/2 + 2 * A(n/2)   n > 1
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * A(n/4))
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * ((n/4)((n/4)+1)/2 + 2 * A(n/8)))
     = ...
     = n(n+1)/2 + sum i from 1 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
     = sum i from 0 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
递归发生
x
次,即直到达到中断条件
B
,并且
n==1
。对于
n:=2^k
,这完全发生在
k
步骤之后-通常我们使用
x:=log2(n)
n
趋于无穷大时。从这里可以得到一个封闭形式的解


请注意,有一些技巧使这更容易:因为我们对计算作业的确切数量不感兴趣,我们可以将
n(n+1)/2
简化为
n^2
,因为它们都在
O(n^2)
中。您可以求解确切的数量或近似值
A(n)=n^2+2*A(n/2)< /代码>,它们都在同一个复杂类中。

让我们考虑一个你已经解决的问题:

void sum2(int n){   
    sum2 = 0;
    for(i=1; i<=n; i++)
        for (j=1; j<=i; j++)
            sum2++;
}

让我们考虑3)

在考虑递归之前,让我们先看看一般情况下的成本(注释
R
):

然后按照输入大小的一半进行两次递归-因此对于
A
我们现在得到:

A(1) = 0
A(n) = n(n+1)/2 + 2 * A(n/2)   n > 1
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * A(n/4))
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * ((n/4)((n/4)+1)/2 + 2 * A(n/8)))
     = ...
     = n(n+1)/2 + sum i from 1 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
     = sum i from 0 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
递归发生
x
次,即直到达到中断条件
B
,并且
n==1
。对于
n:=2^k
,这完全发生在
k
步骤之后-通常我们使用
x:=log2(n)
n
趋于无穷大时。从这里可以得到一个封闭形式的解


请注意,有一些技巧使这更容易:因为我们对计算作业的确切数量不感兴趣,我们可以将
n(n+1)/2
简化为
n^2
,因为它们都在
O(n^2)
中。您可以求解确切的数量或近似值
A(n)=n^2+2*A(n/2)
,它们都属于同一个复杂级别。

@BeyelerStudios迄今为止做得很好;我尽量不重复

我认为您已经掌握了一些基本原则(大部分):

  • 对于普通的线性语句,您需要了解语句复杂性的先验知识。基本算术运算和数组访问是O(1)
  • 语句序列的顺序是该序列中任何语句的最高顺序
  • 决策分支的顺序是任何分支的最高顺序
  • 循环的顺序是循环的重复次数乘以循环体的顺序
  • 递归调用的顺序是递归的重复次数乘以函数体的顺序
现在来看问题4:

这不是O(n^3):请注意,循环不是嵌套的。每个循环都由一个递增语句O(1)组成。前两个循环是O(sqrt(n));第三个循环使用j的最终值加上一个常量,因此也是O(sqrt(n))。请特别注意,您使用的O(sqrt(n)) 问题5:

每个循环都是O(sqrt(n)),但它们现在是嵌套的。这将为您提供sqrt(n)^3或n^(3/2)


未来需要注意的最后一个细节是,sqrt(n)不一定是O(1);它取决于实现。现代芯片上有一个sqrt函数,可以在O(n)时间内处理所有本机整数和浮点。然而,有些数据类型的任意大浮点和整数的实现是O(log(n)).如果您的老师还没有对该操作做出总结性决定,请注意sqrt——以及其他超越函数——潜入循环体。

@BeyelerStudios到目前为止做得很好;我尽量不重复

我认为您已经掌握了一些基本原则(大部分):

  • 对于普通的线性语句,您需要了解语句复杂性的先验知识。基本算术运算和数组访问是O(1)
  • 语句序列的顺序是该序列中任何语句的最高顺序
  • 决策分支的顺序是任何分支的最高顺序
  • 循环的顺序是循环的重复次数乘以循环体的顺序
  • 递归调用的顺序是递归的重复次数乘以函数体的顺序
现在来看问题4:

这不是O(n^3):请注意,循环不是嵌套的。每个循环都由一个递增语句O(1)组成。前两个循环是O(sqrt(n));第三个循环使用j的最终值加上一个常量,因此也是O(sqrt(n))。请特别注意,您使用的O(sqrt(n)) 问题5:

每个循环都是O(sqrt(n)),但它们现在是嵌套的。这将为您提供sqrt(n)^3或n^(3/2)

未来需要注意的最后一个细节是,sqrt(n)不一定是O(1);它取决于实现。现代芯片上有一个sqrt函数,可以在O(n)时间内处理所有本机整数和浮点。然而,有些数据类型的任意大浮点和整数的实现是O(log(n))。如果你的老师还没有对这个操作做出总结性的决定,那就要注意sqrt——以及其他超越函数——是否潜入了一个循环体。

也许,其中一个答案可以帮助你也许,其中一个答案可以帮助你
void sum4(int n){
sum = 0;
for(i=0; i<sqrt(n)/2; i++)
for(j=1; j<8+i; j++)
for(k=j; k<8+j; k++)
sum++;
}
void sum1(int n){
sum1 = 0;             -->  1
for(i=1; i<=n; i++)   -->  n
for (j=1; j<=n; j++)  -->  n^(2)
sum1++;               -->  ?
}
void sum2(int n){   
sum2 = 0;             --> 1
for(i=1; i<=n; i++)   --> n
for (j=1; j<=i; j++)  --> n^(2)
sum2++;               --> ?
}
float useless(a){
n = a.length;               --> ?
if (n==1){
    return a[0];            --> ?
}
    // let a1, a2 be arrays of size n/2
for (i=0; i <= (n/2)-1; i++){         --> n
    a1[i] = a[i];                     --> ?
    a2[i] = a[n/2 +i];                --> ?
}
for (i=0; i<=(n/2)-1; i++){          ---> n+n = n
    for (j = i+1; j<=(n/2) -1; j++){  --->  n^(2)
        if(a1[i] == a2[j])    
    a2[j] = 0;                        --> 1
        }
    }
    b1 = useless(a1);               --> ?
    b2 = useless(a2);               --> ?
    return max(b1,b2);              --> ?
}
void sum3(int n) {
sum = 0;                    --> 1
for(i=0; i<sqrt(n)/2; i++)  --> n
sum++;                      --> ?
for(j=0; j<sqrt(n)/4; j++)  --> n^(2)
sum++;                      --> ?
for(k=0; k<8+j; k++)        --> n^(3)                      
sum++;                      --> ?
}
void sum4(int n){                
sum = 0;                    --> 1
for(i=0; i<sqrt(n)/2; i++)  --> n
for(j=1; j<8+i; j++)        --> n^(2)
for(k=j; k<8+j; k++)        --> n^(3)
sum++;                      --> ?
}
void sum2(int n){   
    sum2 = 0;
    for(i=1; i<=n; i++)
        for (j=1; j<=i; j++)
            sum2++;
}
sum i from 1 to n of [ sum j from 1 to i of (1) ]
= sum i from 1 to n of (i)
= n(n-1)/2
in O(n^2)
float useless(a){
    n = a.length;

    // B: breaking condition
    if (n==1) return a[0];

    // L1: first loop
    // let a1, a2 be arrays of size n/2
    for (i=0; i <= (n/2)-1; i++) {
        a1[i] = a[i];
        a2[i] = a[n/2 +i];
    }

    // L2: second loop
    for (i=0; i<=(n/2)-1; i++) {
        for (j = i+1; j<=(n/2) -1; j++) {
            if(a1[i] == a2[j])
                a2[j] = 0;
        }
    }

    // R: recursion
    b1 = useless(a1);
    b2 = useless(a2);

    return max(b1, b2);
}
A(1) = 0
A(n) = ...           n > 1
B executes 0 assignments
L1 executes 2*n/2 == n assignments
L2 executes at worst (if all elements are 0) n*(n-1)/2 assignments

thus A executes n(n+1)/2 assignments total before reaching R
A(1) = 0
A(n) = n(n+1)/2 + 2 * A(n/2)   n > 1
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * A(n/4))
     = n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * ((n/4)((n/4)+1)/2 + 2 * A(n/8)))
     = ...
     = n(n+1)/2 + sum i from 1 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
     = sum i from 0 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )