【问题标题】:Big O: is this the tightest upper bound for recursive algorithm?Big O:这是递归算法最严格的上限吗?
【发布时间】:2016-05-28 14:33:25
【问题描述】:

我的算法的时间复杂度是否低于O(|2(2 + log3(n)) – 1|)

还有更优雅的写法吗?

int cantor(int low, int high) {
    int gap= (high - low) / 3;

    if (high < low)
        return 0;
    else if (high == low)
        return low;
    else
        return cantor(low, low + gap) + cantor(high - gap, high);
}

运行下面的 Java 程序会产生临界点,其中n = 整数输入,o = 操作数,b = 上限(需要&gt;= o

n    o    b 

0     1     1.0   <- critical point
1     3     3.0   <- critical point
2     3     5.194250610520971
3     7     7.0   <- critical point
4     7     8.592185156484856
5     7     10.04233615383682
6     7     11.388501221041942
7     7     12.65392426064557
8     7     13.85409969044663
9     15    15.0  <- critical point
10    15    16.099749365620383
11    15    17.159572545935887
12    15    18.184370312969712
13    15    19.178087273270823
14    15    20.143957171877723
15    15    21.08467230767364
16    15    22.0025040190721
17    15    22.899390537770895
18    15    23.777002442083877
19    15    24.636792344342172
20    15    25.480033236937405
21    15    26.30784852129114
22    15    27.1212358323658
23    15    27.92108616334829
24    15    28.708199380893266
25    15    29.48329693358293
26    15    30.2470323529008
27    31    31.0  <- critical point

这里是java代码:

public class recursionTreeTimeComplexity {

    static int calls = 0;

    static int cantor(int low, int high) {

        calls++;

        int gap = (high - low) / 3;

        if (high < low)
            return 0;
        else if (high == low)
            return low;
        else
            return cantor(low, low + gap) + cantor(high - gap, high);
    }

    public static void main(String[] args) {

        for (int i = 0; i < 1000; i++) {
            calls = 0;
            cantor(0, i);

            // |(2^log3(n)+2)|-1
            System.out.println(i + "\t" + calls + "\t" + Math.abs((Math.pow(2, ((Math.log(i) / Math.log(3)) + 2)) - 1)));    
        }
    }
}

【问题讨论】:

    标签: java big-o time-complexity binary-search


    【解决方案1】:

    说算法是 O(f(n)) 意味着时间大致与 f(n) 成正比(随着 n 变得足够大)。 [更新: 这并不完全准确,因为实际时间可能会有很大差异,并且不必单调增加。更准确地说,这意味着时间的上限大致与 f(n) 成正比。]

    因此,在使用 O 表示法时添加常数是无关紧要的:O(f(n)+k) 与 O(f(n)) 相同,因为最终 f(n) 部分将占主导地位,而 k部分将变得微不足道。此外,由于这是一个比例,因此乘以常数是无关紧要的; O(kf(n)) 与 O(f(n)) 相同,因为他们都说它基本上与 f(n) 成正比。这意味着原始表达式中的+1 无关紧要,2+ 也是如此,因为 2(2+x) = 4*2x,这意味着你只是乘以一个常数。因此,您的原始表达式可以简化为 O(2^(log3n))。这似乎是正确的;我相信你注意到了,如果 T(n) 是算法的运行时间,那么基本上 T(n) = 2T(n/3) [非常粗略,但这对于这个目的来说已经足够了],这意味着如果我们假设 T(1)=1,那么 T(3)=2,T(9)=4,T(27)=8,等等。

    我们可以进一步简化。 log3n = log2n / log23;因此 2^(log3n) = 2^(log2n / log23) = (2^log2 n)^(1/log23) = n^(1/log23) = n^(log32)。所以算法的时间可以表示为O(n^(log32)),或者大约O(n0.6309)。

    【讨论】:

    • 2^(log3(n)) 插入时不起作用,O(n^(log3(2))) 也不起作用
    • 让我更清楚...我给了你一个关于时间复杂度问题的数学答案。我没想到它会“插入”任何东西,比如一些计算机程序。请解释你用这个公式做了什么来“插入”到某个程序或其他程序,以及这个程序应该用这个公式做什么。关于时间复杂度的 O-notation 答案通常是模糊估计;如果您将它提供给一个对其进行某种检查的程序,那么您可能要求使用不同于我习惯的 O 表示法。
    • 它本身远非成比例
    • 我正在寻找另一种书写方式 |2(2 + log3(n)) – 1| tbh,因为我知道它已经起作用了
    • 我还认为您的问题实际上与“时间复杂度”无关。您正在寻找一个公式,它给出了 exact 操作数的上限。然而,“时间复杂度”并不那么准确。它是关于算法性能形状(或性能上限)的一般性陈述。这就是为什么你可能会看到它说算法 1 是 O(n log n) 算法而算法 2 是 O(n^2) 算法,但你永远不应该看到它们是 O(1.35*n log n) 或O(4*n^2+5.6*n-17)。这不是 时间复杂度 的全部意义所在。
    猜你喜欢
    • 1970-01-01
    • 2019-08-28
    • 2011-01-19
    • 1970-01-01
    • 2016-01-14
    • 2017-02-10
    • 1970-01-01
    • 2023-03-27
    • 2016-06-30
    相关资源
    最近更新 更多