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):
Example 1: Pass-by-value hashtable
and 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 (i.e., a <= 10
for all N
elements), at the termination of the loop, you will have N
elements remaining in hashtable
. Furthermore, each String
in the N
keys in the hashtable
contains up to S
characters. Lastly, each Integer
in the N
values in the hashtable
is constant.
Similarly, you have a possible M
number of strings in list
, where each String
may contain up to S
characters.
Lastly, the Integer a
does not contribute to the analysis because it references memory already accounted for. We can consider this Integer a
constant memory still.
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)
.
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
. Similarly, S
is likely much smaller than both N
and M
. This means the space complexity is 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
.
Example 2: Pass-by-reference hashtable
and list
or elsewhere declared (as in your example)
// 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).
but isn't it reusing the spot of memory a each time making it 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. 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? In the GC case, it would be O(1)
since you are reusing memory. In the "infinite" allocation case, it would be O(N)
since you now have N
spots allocated. 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.
In general, though, if you are referring to reusing the same spot in memory for list
and hashtable
each iteration, the answer is simpler. 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. Therefore, regardless of whether it reuses the same or different spots in memory, they both still contribute to a linear space complexity.
tl;dr
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. Therefore, this method will be O(1)
.