破解编码面试第六版:大O怀疑

时间:2018-11-27 21:49:55

标签: java

  

“ ...对于特定的输入,O(N)代码的运行速度可能比0(1)代码快。大的O仅描述增加的速率。”

根据我的理解:-

  • O(N)-基于输入N的变化值运行算法所需的时间。
  • O(1)-算法执行所需的恒定时间,与输入大小无关,例如int val = arr [10000];

有人可以根据作者的陈述帮助我理解吗?

  1. O(N)代码比O(1)运行得快吗?
  2. 作者暗示的具体投入是什么?
  3. 增加率是多少?

预先感谢

2 个答案:

答案 0 :(得分:3)

O(n)恒定时间可以绝对快于O(1)线性时间。原因是在Big O中完全忽略了恒定时间操作,这是一种算法的运行时间随着输入大小 n 的增加而增加的速度的度量,而没有其他值。

这是一个例子:

int constant(int[] arr) {
    int total = 0;

    for (int i = 0; i < 10000; i++) {
         total += arr[0];
    }

    return total;
}

int linear(int[] arr) {
    int total = 0;        

    for (int i = 0; i < arr.length; i++) {
        total += arr[i];
    }

    return total;
}

在这种情况下,constant会做很多工作,但是无论arr有多大,它都是固定不变的工作。另一方面,linear似乎没有多少操作,但是这些操作取决于arr的大小。

换句话说,随着arr的长度增加,constant的性能保持不变,但是linear的运行时间与其参数数组的大小成线性比例增加。

使用单项数组调用两个函数,例如

constant(new int[] {1}); 
linear(new int[] {1});

很明显constant的运行速度比linear慢。

但是像这样称呼他们

int[] arr = new int[10000000];

constant(arr);
linear(arr);

哪个运行速度较慢?

考虑之后,run the code here给出了 n 的各种输入并比较结果。


只是为了证明run time != Big O的这种现象不仅适用于恒定时间函数,请考虑:

void exponential(int n) throws InterruptedException {
    for (int i = 0; i < Math.pow(2, n); i++) {
        Thread.sleep(1);
    }
}

void linear(int n) throws InterruptedException {
    for (int i = 0; i < n; i++) {
        Thread.sleep(10);
    }
}

锻炼(用笔和纸):nexponential运行linear的速度快?

答案 1 :(得分:1)

请考虑以下情形:

Op1)给定一个长度为n的数组,其中n> = 10,在控制台上打印前十个元素两次。 ->这是恒定时间(O(1))操作,因为对于任何大小> = 10的数组,它将执行20个步骤。

Op2)给定长度为n的数组,其中n> = 10,找到数组中最大的元素。这是恒定时间(O(N))操作,因为对于任何数组,它将执行N个步骤。

现在,如果数组大小在10到20(不包括)之间,则Op1将比Op2慢。但是,假设我们采用一个尺寸大于20(例如,尺寸= 1000)的数组,Op1仍然需要20个步骤来完成,而Op2将需要1000个步骤来完成。

这就是为什么big-o表示关于算法复杂度的增长(增长率)的原因