它是is said O(1)操作的一个例子是访问数组中的元素。根据一个source,O(1)可以用以下方式定义:
[Big-O of 1]表示算法的执行时间不依赖于 输入的大小。它的执行时间是不变的。
但是,如果想要访问数组中的元素,操作的效率是否取决于数组中的元素数量?例如
int[] arr = new int[1000000];
addElements(arr, 1000000); //A function which adds 1 million arbitrary integers to the array.
int foo = arr[55];
我不明白最后一个语句如何描述为在O(1)中运行;数组中的1,000,000个元素是否与运行的运行时间有关?当然,找到元素55需要的时间比元素1要长?如果有的话,这对我来说就像O(n)。
我确定我的推理存在缺陷,但是,我只是想澄清如何在O(1)中运行?
答案 0 :(得分:13)
Array是一种数据结构,其中对象存储在连续的内存位置。所以原则上,如果您知道基础对象的地址,您将能够找到ith
对象的地址。
addr(a[i]) = addr(a[0]) + i*size(object)
这使得访问数组O(1)的ith
元素。
修改强>
从理论上讲,当我们谈论访问数组元素的复杂性时,我们会讨论固定索引i
输入大小= O(n)
要访问ith
元素,addr(a[0]) + i*size(object)
。该术语与n
无关,因此可以说是O(1)。
乘法仍然取决于i
,但不取决于n
。它是常数O(1)。
答案 1 :(得分:4)
内存中元素的地址将是数组的基地址加上索引乘以数组中元素的大小。因此,要访问该元素,您只需访问memory_location + 55 * sizeof(int)
。
这当然假设你在假设乘法需要恒定的时间而不管输入的大小,如果你是very precise
,这可能是不正确的答案 2 :(得分:2)
要查找元素不是O(1) - 但是访问数组中的元素与查找元素无关 - 确切地说,您不与其他元素交互,您不需要访问除了你的单个元素之外的任何东西 - 你总是计算地址,无论数组有多大,那就是单个操作 - 因此O(1)。
答案 3 :(得分:1)
如果我们说下标运算符(索引)具有O(1)时间复杂度,我们将此语句排除在任何其他操作/语句/表达式等的运行时之外。因此addElements
不会影响操作。
肯定找到元素55需要的时间比元素1要长?
“查找”?不好了! “查找”意味着相对复杂的搜索操作。我们知道数组的基地址。要确定arr[55]
处的值,我们只需将55
1 添加到基址并检索该内存位置的值。这肯定是O(1)。
1 由于int
数组的每个元素至少占用两个字节(使用C时),因此不完全正确。 55
需要首先乘以int
的大小。
答案 4 :(得分:1)
Arrays连续存储数据,与Linked Lists或Trees或Graphs或其他使用引用的数据结构不同,可以查找下一个/上一个元素。
您可以直观地看出第一个元素的访问时间是O(1)。但是您觉得55 th 元素的访问时间是O(55)。那是你弄错了的地方。你知道第一个元素的地址,所以它的访问时间是O(1)。
但是你也知道55 th 元素的地址。它只是1 st + size_of_each_element * 54的地址。
因此,您可以在O(1)时间内访问该元素以及数组的任何其他元素。这就是为什么你不能在数组中包含多个类型的元素的原因,因为这会完全弄乱数学以找到数组的n th 元素的地址。
因此,对数组中任何元素的访问是O(1),所有元素都必须是相同的类型。
答案 5 :(得分:1)
理论上,阵列访问是O(1),正如其他人已经解释的那样,我想你的问题或多或少都是理论问题。我仍然喜欢引入另一个方面。
实际上,如果数组变大,数组访问速度会变慢。有两个原因:
答案 6 :(得分:1)
为声明生成的机器代码(或者,对于Java,虚拟机器代码)
int foo = arr[55];
本质上是:
这三条指令在标准机器上都需要O(1)时间。