2
def minAbsDifference(self, nums: List[int], goal: int) -> int:4
# When goal 0 we can just choose no elements10
# Split the list in 2 parts and then find all possible subset sums11
# T = O(2^n/2) to build all subset sums14
rightList = nums[mid:]17
# T = O(2^n/2) to build all subset sums (we only consider half list)18
def buildSubsetSums(usedNums, numsToChooseFrom, ind, storeIn):19
if ind == len(numsToChooseFrom):20
# We also keep elements with sum 0 to deal with cases like this where we don't select nums21
# List: [1,2,3], Target: -7 (choosing no elements will give a sum close to goal)22
# We can also have cases where we want to take only 1 element from the list23
# so sum 0 for left and right list needs to be an option24
storeIn.append(sum(usedNums))27
usedNums.append(numsToChooseFrom[ind])28
buildSubsetSums(usedNums, numsToChooseFrom, ind + 1, storeIn)30
buildSubsetSums(usedNums, numsToChooseFrom, ind + 1, storeIn)32
buildSubsetSums([], leftList, 0, leftSums)33
buildSubsetSums([], rightList, 0, rightSums)34
# 2^n/2 log(2^n/2) = n/2 * 2^n/2 time to sort39
# Loop runs 2^n/2 times and inside binary search tale n/2 time40
# So total time is n/2 * 2^n/241
for leftSum in leftSums:42
complement = goal - leftSum43
# Bisect left takes log(2^n/2) = n/2 search time44
idx = bisect.bisect_left(rightSums, complement)46
for i in [idx - 1, idx, idx + 1]:47
if 0 <= i < len(rightSums):48
finalSum = leftSum + rightSums[i]49
diff = min(diff, abs(goal - finalSum))51
# Over all time complexity is - n/2 * 2^n/252
# 1. Making subset sums will take - 2^n/253
# 2. Sorting right list takes - 2^n/2 * n/254
# 3. Iterating one list and finding closest complement in other56
# Space will be O(n/2) for the list and call stack for building subset