我很难使用O(n)原理来推广算法的时间复杂度,该算法的具体时间复杂度为O(sum(a)),其中a是整数数组。
我的直觉是,这个时间复杂度应该推广到O(n),因为你可以把它想象为ki值的“线性”方程出现n次,其中k是数组中的整数值,使其成为O( n)(对于直线上升的O(n)情况,k = 1)。
但它似乎与O(n)不完全相同 - k的值可能远大于n,如果所有这些k值都大,那么你可以得到O(n ^ 2) )或O(n ^ 3)取决于该值的大小。
O(n)复杂度是否需要考虑这一点,其中n是数组的长度?我真的应该将n定义为数组中所有元素的总和而不是数组的长度吗?
一般来说,考虑这个问题的最佳方法是什么?
答案 0 :(得分:0)
从根本上说,我们希望根据输入描述算法的运行时间。 “运行时”是一个模糊的术语,通常在地毯下扫过。例如,排序算法或散列表操作的“运行时”是在比较次数中测量的,但使用“运行时”来表示基本操作的数量(通常也只是模糊地定义)也是可能的。
计算运行时经常会有两种选择(或简化)。第一种,是忽略实际输入,并使用输入的大小(以某种方式测量)代替。此大小通常表示为n
。第二种方法是使用big-O表示法来描述最坏情况(或最佳情况,或平均值,或摊销......)。
这些选择都不一定是必要的,有时它们没有意义。重复一遍,因为这是答案的关键:描述n
的big-O中的运行时不是描述运行时的唯一方法,有时这样做是没有意义的。
例如,对于在O(sum(a))
时间内运行的算法:
func f(a) {
t = 0
for x in a {
for i = 1..x {
t += 1
}
}
}
使用输入数组a
的长度来描述此运行时没有用。它没用,因为a
的长度没有说明最坏情况的运行时。
说t
递增sum(a)
次是关于程序运行时的有用声明。它不使用大O复杂符号。
如果你做想用big-O表示法来表达,你可以说这段代码的运行时是O(sum(a))
。这完全模糊了您在运行时测量的内容,因为除了递增t
之外,您可以包括执行语句的成本。
回到示例,你可以(如果你正在研究复杂性类,你可能会)说n
是大小(在比特)输入数组。然后你可以说一下运行时(在基本操作中测量):它是O(2 ^ n),因为最坏情况输入是一个数组,其中一个元素取值为2 ^ n-1(* note)。
*注意:这忽略了有关如何使用位编码数组的一些技术细节。