Problem: Given an array that sums to 0, find the maximum number of partitions of it such that all of them sum up to 0 individually.
Example:
- input: [-2, 4, -3, 5, -4]
- output: 2 (which are [[5, -2, -3], [-4, 4]]. These are not necessarily needed as the output of the algorithm)
My solution:
I find any subset from the initial list that sums up to 0 and is a proper subset (function f in the code below finds that any subset). Its disjoint is also an answer. Then I run the same algorithm on what I found.
def return_n_subsets(balances):
balances.sort()
n = len(balances)
if n == 0:
return 0
@cache
def f(sp, cur_sum):
if sp == len(balances):
return None
if balances[sp] == -cur_sum:
return [balances[sp]]
if cur_sum > 0: #early stop since there would be only positive numbers from here on
return None
#include sp
out1 = f(sp+1, cur_sum + balances[sp])
if out1 is not None:
out1 = out1[:] #############################
out1.append(balances[sp])
if len(out1) != len(balances): #condition to not return the input itself
return out1
#dont include sp
out2 = f(sp+1, cur_sum)
if out2 is not None:
out2 = out2[:] ##############################
return out2
return None
sub1 = f(0,0)
if sub1 is None:
return 1
[balances.remove(i) for i in sub1]
subsets = [sub1, balances]
out = 0
while True:
new_subsets = []
for balances in subsets:
balances.sort()
f.cache_clear()
sub1 = f(0, 0)
if sub1 is not None:
[balances.remove(i) for i in sub1]
new_subsets.append(balances)
new_subsets.append(sub1)
else:
out += 1
if len(new_subsets) == 0:
break
subsets = new_subsets
return out
My computation of the time complexity:
I am going through every subset of the original list and at each iteration im also creating a copy of the output list (lines in code with lots of hashes after them). This is Nx2^N. Then I get 2 subsets of size N/2 each and I run 2xN/2x2^(N/2). Then I run 4xN/4x2^(N/4) and so on and so forth.
Overall time complexity: O(Nx2^N + Nx2^(N/2) + Nx2^(N/4) ...) = O(Nx(2^N + 2^(N/2) + 2^(N/4) ...)) = O(Nx2^N)
- Is my computation of the time complexity accurate? I am confused since I am using memoization it would appear that I am actually solving only N*S problems where S is the possible sums which would range from the sum of all the negative numbers to the sum of all the positive numbers. A bit confused as to which is accurate.
- Are there improvements I can make to my algorithm?
[-3, -2, -1, 1, 2, 3]and got5.outinitialised with a value 2. It would overestimate everything by 2. I pasted a part of a much bigger code and forgot to make this change. The code is wrong even after that. It passed all the test cases on leetcode and also beat 100% of other solutions and hence I assumed it is right. Thank you for your example. The code is wrong because "I cannot find any 0-sum subset and try to break it further till I can and say that is the solution."