我在使用以下算法时遇到了一些问题:
for (int i = 1; i < n; i = 2i)
for (int j = i; j < n; j++)
// do something (const time)
因此,显示运行时为O(nlogn)并不太难 - 但我不确定如何显示它是Big Omega(nlogn)!直观地说,我认为情况必然如此,因为对于给定的n,时间复杂度在最佳/最差情况之间不会有所不同。
任何建议都将非常感谢!
答案 0 :(得分:1)
在此算法中,没有最佳或最差执行路径:给定n
的值,执行路径是固定的。所以最好和最坏的情况都是一样的。
一个好的经验法则是,如果算法的控制流程不是数据驱动的,那么最佳和最差的情况都是相同的。
我所说的数据驱动的一个例子是快速排序算法的实现,其中枢轴总是被选择为数组的第一个元素。有时,第一个元素将完美地分割其余数据(最好的情况),有时它将是最大值或最小值(最坏情况)。
答案 1 :(得分:0)
要看到为什么这是O(nlogn)的直觉,我们需要做的就是看内循环执行多少次。
正如你所说,外循环执行logn
次(很容易看到,因为在不等式停止持有之前你只能加倍i
logn
次)
因此对于内部循环,我们可以看到每次i
更改时它会执行不同数量的步骤
第一次迭代,它执行n-1
次(i
开始于1
)
下一次迭代n-2
第三次迭代n-4
我们可以看到模式为(n-1) + (n-2) + (n-4) + (n-8) ...
现在,让我们将n's
分开。我们有多少(n-k)
个新增内容?通过了解外循环执行的次数,我们得到logn
。
因此n + n + n + n ... - 1 - 2 - 4 - 8...
可以被视为nlogn - 1 - 2 - 4 - 8 ...
现在,我们如何表明这可以进一步减少?我们减去的总数是logn
减法(由于外循环),我们知道减法的大小每次都会增加一倍。查看它的另一种方法是来自i = 0 to logn
2^i
的总和。
现在,sum of i = 0 to n
2^i
的标准CS公式为2^(n+1) - 1
。例如,这用于显示完整二叉树中的最大节点数,您可以通过归纳来证明它。
因此,我们将logn
替换为公式中的n
,我们得到nlogn - (2^(logn+1)- 1)
。但我们还没有完成。我们可以证明2^(logn+1) = 2*2^logn=2*n
。最后,我们最终得到了nlogn - 2n + 1
。此时,设置不等式并找到c2
。