2

The time complexity of this code to create a powerset from distinct integers is listed as O(n * 2^n) at all places including the Leetcode solution.

I listed the complexity of each step as a code comment and for me the overall complexity is coming out as O(n^2 * 2^n). You can see we are looping over n times on a line of code whose own complexity is O(n * 2^n), thus, shouldn't be the time complexity of this solution be O(n^2 * 2^n)?

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        output = [[]]
        
        for num in nums: # O(n)
            output += [curr + [num] for curr in output] # n for adding two lists and then 2^n times so O(n * 2^n)
        
        return output
3
  • 1
    @ShadowRanger There is no n_0 and c such that for all n > n_0, n * 2^n < c * 2^n. Informally, you can discard lower order terms but not lower order factors. Commented Sep 22, 2022 at 2:21
  • 1
    @ShadowRanger Big O is a mathematical concept with a formal definition; it does not depend on what is "relevant" to a programmer, and in fact is not even specifically used only in computer science. Whether or not the difference between O(2^n) and O(n^2 * 2^n) is relevant for a given purpose, they are different - unlike, say, O(2^n) and O(n^2 + 2^n), which are the same. Commented Sep 22, 2022 at 2:51
  • @KellyBundy: That's a better analogy I accept. I'm burninating my comments; in practice, I do treat exponential as making the polynomial term irrelevant, and I can't think of any scenario where the additional n * factor will ever matter, but yeah, formally, it can't be dropped. (I'd leave the comments, but I think this is distracting from the OP's problem, not helping) Commented Sep 22, 2022 at 2:58

1 Answer 1

4

The code can be rewritten as follows:

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        output = [[]]
        
        for k, num in enumerate(nums):
            new_items = [curr + [num] for curr in output] # O(2^k * (k+1))
            output += new_items # O(2^k)
            
        return output

The time complexity of the k-th iteration of the loop is O(2^k * (k+1) + 2^k) = O(2^k * (k+2)). To get the complexity of the whole loop, we need to take the sum of the the expressions 2^k * (k+2) from k=0 to k=n-1, This sum is 2^n * n.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't see you accounting for all the deletions of the temporary new_items lists, but that only adds O(n), so doesn't matter.
@KellyBundy There are also other O(n) contributions: retrieval of num from the lists nums, creation of the temporary list assigned to new_items, assignment of this list to new_items. But, as you wrote, this does not matter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.