我最近接受了一次采访,并且遇到了一个我要编写代码的小问题。
问题基本上是在长度为n的数组中找到重复,使用O(n)中的常量空间。每个元素在1-(n-1)范围内,并保证是重复的。这就是我想出的:
public int findDuplicate(int[] vals) {
int indexSum=0;
int valSum=0;
for (int i=0; i< vals.length; i++) {
indexSum += i;
valSum += vals[i];
}
return valSum - indexSum;
}
然后我们讨论了这个算法的运行时间。 0 - >的系列之和n =(n ^ 2 + n)/ 2是二次的。但是,算法是不是O(n)时间?操作数量是否受到数组长度的限制?
我错过了什么?这个算法是O(n ^ 2)?
答案 0 :(得分:5)
0
到n
的整数之和为O(n^2)
的事实与此无关。
是的,你完全O(n)
次完成循环。
最大的问题是,你在加入时假设的复杂程度是多少?
如果O(1)
那么是的,这是线性的。大多数人会认为加法是O(1)
。
但是,如果实际添加O(b)
(b
是位,在我们的情况下是b = log n
),那该怎么办?如果你假设这个,那么这个算法实际上是O(n * log n)
(添加n
个数字,每个都需要log n
个比特来代表。)
同样,大多数人都认为添加是O(1)
。
答案 1 :(得分:2)
算法研究人员已经对单位成本RAM 模型进行了标准化,其中单词是Theta(log n)位,单词上的操作是Theta(1)时间。一个替代模型,其中对单词的操作是Theta(log n)时间不再使用,因为拥有can't recognize palindromes in linear time的RAM是荒谬的。
您的算法明确地在时间O(n)和额外空间O(1)中运行,因为约定是将空间的默认单位作为单词。你的面试官可能一直担心溢出,但是如果以M≥n的任何数量模拟加法和减法,你的算法就能正常工作,就像两个补码的情况一样。
无论你的面试官的问题是想象的还是根植于对理论计算机科学惯例的不正确理解。答案 2 :(得分:1)
是的,算法是线性的*。 valSum
的结果不会影响运行时间。把它变为极端,功能
int f(int[] vals) {
return vals.length * vals.length;
}
在1次乘法中给出n 2 。显然这并不意味着f
是O(n 2 );)
(*:假设加法是O(1))
答案 3 :(得分:1)
您每次在n
个单元格上处理一次。线性时间。
答案 4 :(得分:0)
从i = 0到n的i之和是n *(n + 1)/ 2,它由n^2
限定,但与运行时间无关......这只是封闭形式的总结。
算法的运行时间是线性的,O(n)
,其中n是数组中元素的数量(假设加法运算是一个恒定时间运算,O(1)
)。
我希望这会有所帮助 赫里斯托斯