[英]Is this function (for loop) space complexity O(1) or O(n)?
public void check_10() {
for (string i : list) {
Integer a = hashtable.get(i);
if (a > 10) {
hashtable.remove(i);
}
}
}
Would this be O(1) or O(n)? 这是O(1)还是O(n)? I'm guessing O(n), but isn't it reusing the spot of memory a each time making it O(1)?
我猜O(n),但不是每次重复使用内存点O(1)?
Space complexity asks "how much additional space (asymptotically, speaking) am I using in this snippet of code". 空间复杂性问“我在这段代码中使用了多少额外空间(渐近,说话)”。 Here's how a space complexity analysis would work, showing two general cases (for your code snippet):
以下是空间复杂度分析的工作原理,显示了两个一般情况(对于您的代码片段):
hashtable
and list
hashtable
和list
// assume `list` and `hashtable` are passed by value
public void check_10(List<String> list, HashMap<String, Integer> hashtable) {
for (String i : list) {
Integer a = hashtable.get(i);
if (a > 10) {
hashtable.remove(i);
}
}
}
Assuming you have N
elements in hashtable
and no elements are removed (ie, a <= 10
for all N
elements), at the termination of the loop, you will have N
elements remaining in hashtable
. 假设您在
hashtable
有N
元素并且没有删除任何元素(即,对于所有N
元素, a <= 10
),在循环终止时,您将在hashtable
保留N
元素。 Furthermore, each String
in the N
keys in the hashtable
contains up to S
characters. 此外,
hashtable
中N
键中的每个String
最多包含S
字符。 Lastly, each Integer
in the N
values in the hashtable
is constant. 最后,
hashtable
N
值中的每个Integer
都是常量。
Similarly, you have a possible M
number of strings in list
, where each String
may contain up to S
characters. 同样,
list
可能有M
个字符串,其中每个String
最多可包含S
字符。
Lastly, the Integer a
does not contribute to the analysis because it references memory already accounted for. 最后,
Integer a
对分析没有贡献,因为它引用了已经占用的内存。 We can consider this Integer a
constant memory still. 我们可以认为这个
Integer a
仍然Integer a
恒定的记忆。
Therefore, assuming hashtable
and list
had been declared in the method, you are looking at a space complexity of O(N*S + M*S + I)
. 因此,假设在方法中声明了
hashtable
和list
,您将看到O(N*S + M*S + I)
的空间复杂度O(N*S + M*S + I)
。
That said, asymptotically, we don't really care about I
(the Integer a
) because it is constant size that is likely much smaller than N
and M
. 也就是说,渐渐地,我们并不真正关心
I
( Integer a
)因为它是恒定的大小,可能比N
和M
小得多。 Similarly, S
is likely much smaller than both N
and M
. 类似地,
S
可能比N
和M
都小得多。 This means the space complexity is O(N + M)
. 这意味着空间复杂度为
O(N + M)
。 Because both are linear terms, we can (carefully) reduce this to O(n)
, where n
is a linear term that is a linear combination of N and M
. 因为两者都是线性项,我们可以(小心地)将其减少为
O(n)
,其中n
是线性项,它是N and M
的线性组合。
hashtable
and list
or elsewhere declared (as in your example) hashtable
和list
或其他声明的内容(如示例中所示) // assume `list` and `hashtable` are passed by reference or
// declared elsewhere in the class as in
//
// public void check_10() {
public void check_10(List<String> list, HashMap<String, Integer> hashtable) {
for (String i : list) {
Integer a = hashtable.get(i);
if (a > 10) {
hashtable.remove(i);
}
}
}
In this method, list
and hashtable
have already been allocated elsewhere, which means that the space complexity for this method is O(1)
because we are only using constant space in Integer a
and String i
(even though technically, they are references to previously allocated memory -- you can consider the constant space as a result of storing the reference). 在这个方法中,
list
和hashtable
已经在别处分配了,这意味着这个方法的空间复杂度是O(1)
因为我们只在Integer a
和String i
使用常量空间(尽管从技术上讲,它们是对先前的引用)分配内存 - 您可以考虑存储引用的常量空间)。
but isn't it reusing the spot of memory a each time making it O(1)?
但是不是每次重复使用记忆点O(1)?
It depends on what you mean by "reusing" the spot in memory. 这取决于你在内存中“重复使用”这个位置的含义。 In theory, space complexity analysis does not exactly consider the implementation details of the language in this sense.
从理论上讲,空间复杂性分析并没有从这个意义上准确地考虑语言的实现细节。 This means that if you had a loop like
这意味着如果你有一个像这样的循环
for (int i = 0; i < N; i++) {
T myvar = new T();
}
you don't consider the implications of what's happening to myvar
after each loop iteration. 你不考虑每次循环迭代后
myvar
发生的事情的含义。 By "implications of what's happening" I mean, does the garbage collector reclaim memory after each iteration or are you continually allocating N spots of memory on the heap? 通过“对正在发生的事情的影响”我的意思是,垃圾收集器是在每次迭代后回收内存还是你不断在堆上分配N个内存点? In the GC case, it would be
O(1)
since you are reusing memory. 在GC情况下,由于您正在重用内存,因此它将是
O(1)
。 In the "infinite" allocation case, it would be O(N)
since you now have N
spots allocated. 在“无限”分配情况下,它将是
O(N)
因为您现在已经分配了N
点。 Again, in theory, this is usually not considered in the analysis, and any T myvar = new T()
is usually considered to be O(1) regardless of whether it sits in a loop or not. 同样,理论上,这通常不在分析中考虑,并且任何
T myvar = new T()
通常被认为是O(1),无论它是否位于循环中。
In general, though, if you are referring to reusing the same spot in memory for list
and hashtable
each iteration, the answer is simpler. 但是,一般情况下,如果您指的是在每次迭代中重复使用内存中的相同位置
list
和hashtable
,答案就更简单了。 Consider the following: 考虑以下:
public void foo() {
int list[] = {1, 2, 3, 4};
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
}
Even though list
is declared once and we're only iterating through list
and printing the contents, foo()
is still O(n) in memory complexity because we have allocated list
, where in the asymptotic case could have up to n
elements. 即使
list
被声明一次并且我们只是遍历list
并打印内容, foo()
仍然是内存复杂度的O(n),因为我们已经分配了list
,其中渐近情况下最多可以有n
元素。 Therefore, regardless of whether it reuses the same or different spots in memory, they both still contribute to a linear space complexity. 因此,无论它是否在内存中重用相同或不同的点,它们都仍然有助于线性空间复杂性。
In your specific case, though, both list
and hashtable
had already been allocated elsewhere in the program and are not introduced here, so they do not contribute to the complexity, and Integer a
and String i
are only constant in memory. 但是,在您的特定情况下,
list
和hashtable
都已经在程序的其他地方分配,并且未在此处介绍,因此它们不会导致复杂性,并且Integer a
和String i
仅在内存中保持不变。 Therefore, this method will be O(1)
. 因此,这种方法将是
O(1)
。
Other than 2 constant sized variables string i
and Integer a
this method does not allocate any extra space. 除了2个常量大小的变量
string i
和Integer a
此方法不会分配任何额外的空间。 Which means this loop clearly has constant space complexity .ie. 这意味着这个循环显然具有恒定的空间复杂性。 O(1) .
O(1) 。
To clarify it further, I would rather ask you a question : 为了进一步澄清,我宁愿问你一个问题:
Do you call (iterative)binary search an O(n) space complexity algorithm ?
你是否称为(迭代)二进制搜索O(n)空间复杂度算法?
Absolutely not. 绝对不。
Your function check_10() uses a preallocated list and hash table (just like iterative binary search uses preallocated sorted array) and 2 constant space variables so it has O(1) space complexity. 您的函数check_10()使用预分配列表和哈希表(就像迭代二进制搜索使用预分配的排序数组)和2个常量空间变量,因此它具有O(1)空间复杂度。
PS : I am clarifying the doubt raised by OP in comments of this answer from here onwards -> PS :我正在澄清OP在此回答的评论中提出的疑问 - >
As pointed out by MichaelRecachinas, String
and Integer
in this loop are references. 正如MichaelRecachinas所指出的,这个循环中的
String
和Integer
是引用。 They are not a copy so they won't contribute anything to the space complexity of this function. 它们不是副本,因此它们不会对此功能的空间复杂性做出任何贡献。
PPS : Integer a
and String i
are allocated memory only once and then are reused in each iteration of the loop. PPS :
Integer a
和String i
只分配一次内存,然后在循环的每次迭代中重用。
This has O(n) space complexity because the list takes up that space. 这具有O(n)空间复杂度,因为列表占用了该空间。 :).
:)。 The hash table is at most another O(n), so the sum of the space complexities is still O(n).
哈希表最多是另一个O(n),因此空间复杂度的总和仍然是O(n)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.