简体   繁体   English

这段代码的 Big O 时间复杂度是多少?

[英]What's the Big O time complexity of this code?

#include <stdio.h>

int F(int L[], int p, int q) {
    if (p < q) {
        int r, f1, f2;
        r = (p + q) / 2;
        f1 = 2 * F(L, p, r);
        f2 = 2 * F(L, r + 1, q);
        return f1 + f2;
    } else if (p == q) {
        return L[p] * L[p];
    }else{
        return 0;
    }
}

int main(void) {
    int arr[8] = {1,2,3,4,5,6,7};
    printf("%d", F(arr, 0, 7));
}

Someone said the time complexity of this code is O(n) .有人说这段代码的时间复杂度是O(n)

I don't understand it at all...我完全不明白...

Isn't it O(logN) ???不是O(logN)吗???

Answer: The Big-O complexity is O(N)答案:Big-O 复杂度为 O(N)

Explanation:解释:

The program takes a range of some size (ie q - p + 1 ) and cut that range into 2 half.该程序采用一定大小的范围(即q - p + 1 )并将该范围切成两半。 Then it calls the function recursively on these two half ranges.然后它在这两个半范围内递归调用 function。

That process continues until the range has size 1 (ie p == q ).该过程一直持续到范围的大小为 1(即p == q )。 Then there is no more recursion.然后就没有递归了。

Example: Consider a start range with size 8 (eg p=0, q=7 ) then you will get示例:考虑大小为 8 的起始范围(例如p=0, q=7 ),然后您将得到

1 call with range size 8
2 calls with range size 4
4 calls with range size 2
8 calls with range size 1

So 7 calls (ie 1+2+4) with range size greater than 1 and 8 calls with range size equal to 1. A total of 15 calls which is nearly 2 times the starting range size.因此,范围大小大于 1 的 7 个调用(即 1+2+4)和范围大小等于 1 的 8 个调用。总共 15 个调用,几乎是起始范围大小的 2 倍。

So for a range size being a power of 2, you can generalize to be因此,对于范围大小为 2 的幂,您可以概括为

Number of calls with range size greater than 1: 

    1+2+4+8+16+...+ rangesize/2 = rangesize - 1

Number of calls with range size equal to 1: 

    rangesize

So there will be exactly 2 * rangesize - 1 function calls when range size is a power of 2.因此,当范围大小为 2 的幂时,将恰好有2 * rangesize - 1 function 次调用。

That is Big-O complexity O(N).那就是 Big-O 复杂度 O(N)。

Want to try it out?想尝试一下吗?

#include <stdio.h>

unsigned total_calls = 0;
unsigned calls_with_range_size_greater_than_one = 0;
unsigned calls_with_range_size_equal_one = 0;

int F(int L[], int p, int q) {
    ++total_calls;
    if (p < q) {
        ++calls_with_range_size_greater_than_one;
        int r, f1, f2;
        r = (p + q) / 2;
        f1 = 2 * F(L, p, r);
        f2 = 2 * F(L, r + 1, q);
        return f1 + f2;
    } else if (p == q) {
        ++calls_with_range_size_equal_one;
        return L[p] * L[p];
    }else{
        return 0;
    }
}

int arr[200] = {1,2,3,4,5,6,7};

int main(void) {
    
    for (int i=3; i < 128; i = i + i + 1)
    {
        total_calls=0;
        calls_with_range_size_greater_than_one=0;
        calls_with_range_size_equal_one=0;
        F(arr, 0, i);
        printf("Start range size: %3d -> total_calls: %3u calls_with_range_size_greater_than_one: %3u calls_with_range_size_equal_one: %3u\n", i+1, total_calls, calls_with_range_size_greater_than_one, calls_with_range_size_equal_one);
    }
    return 0;
}

Output: Output:

Start range size:   4 -> total_calls:   7 calls_with_range_size_greater_than_one:   3 calls_with_range_size_equal_one:   4
Start range size:   8 -> total_calls:  15 calls_with_range_size_greater_than_one:   7 calls_with_range_size_equal_one:   8
Start range size:  16 -> total_calls:  31 calls_with_range_size_greater_than_one:  15 calls_with_range_size_equal_one:  16
Start range size:  32 -> total_calls:  63 calls_with_range_size_greater_than_one:  31 calls_with_range_size_equal_one:  32
Start range size:  64 -> total_calls: 127 calls_with_range_size_greater_than_one:  63 calls_with_range_size_equal_one:  64
Start range size: 128 -> total_calls: 255 calls_with_range_size_greater_than_one: 127 calls_with_range_size_equal_one: 128

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM