I am trying to understand difference/similarity in complexities when writing the code to generate powerset in 2 ways:
def powerset(s, i, cur):
if i==len(s):
print(cur)
return
powerset(s, i+1, cur+s[i]) # string addition is also possibly O(n^2) here?
powerset(s, i+1, cur)
powerset("abc", 0, "")
Output:
['abc', 'ab', 'ac', 'a', 'bc', 'b', 'c', '']
This is going into recursion, with 2 choices at each step (adding s[i] or not), creating 2 branches. Leading to 2^n and adding to the array/printing is another O(n), leading to O(n*2^n)
Also thinking about it in the terms of branches^depth = O(2^n)
The space complexity for this will be: O(n)? Considering max depth of the tree to go up to n by the above logic.
And with this:
s = "abc"
res = [""]
for i in s:
res += [j+i for j in res]
I get the same output.
But here, I see 2 for loops and the additional complexity for creating the strings -- which is possibly O(n^2) in Python. Leading to possible O(N^4) as opposed to O(n*2^n) in the solution above.
Space complexity here seems to me to be O(n) since we are reserving space for just the output. But no additional space, so overall: O(1)
Is my understanding for these solutions in time and space correct? I was under the impression that computing powerset is O(2^n). But I figured maybe its a more optimized solution? (even though the second solution seems more naive).
https://stackoverflow.com/questions/34008010/is-the-time-complexity-of-iterative-string-append-actually-on2-or-on
Here, they suggest using arrays to avoid the `O(n^2)` complexity of string concatenation.