You are given an integer array nums
and an integer goal
.
You want to choose a subsequence of nums
such that the sum of its elements is the closest possible to goal
. That is, if the sum of the subsequence's elements is sum
, then you want to minimize the absolute difference abs(sum - goal)
.
Return the minimum possible value of abs(sum - goal)
.
Note that a subsequence of an array is an array formed by removing some elements (possibly all or none) of the original array.
Example 1:
Input: nums = [5,-7,3,5], goal = 6 Output: 0 Explanation: Choose the whole array as a subsequence, with a sum of 6. This is equal to the goal, so the absolute difference is 0.
Example 2:
Input: nums = [7,-9,15,-2], goal = -5 Output: 1 Explanation: Choose the subsequence [7,-9,-2], with a sum of -4. The absolute difference is abs(-4 - (-5)) = abs(1) = 1, which is the minimum.
Example 3:
Input: nums = [1,2,3], goal = -7 Output: 7
Constraints:
1 <= nums.length <= 40
-107 <= nums[i] <= 107
-109 <= goal <= 109
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach tries every single possible combination of numbers from the input to find the subsequence sum that's closest to the target. We consider all possible subsequences, calculate their sums, and compare each sum to the target value.
Here's how the algorithm would work step-by-step:
def closest_subsequence_sum_brute_force(numbers, target):
closest_sum = float('inf')
# Iterate through all possible subsequences
for i in range(1 << len(numbers)):
current_subsequence_sum = 0
# Build the subsequence and calculate its sum
for j in range(len(numbers)):
# Check if the j-th element is included in the subsequence
if (i >> j) & 1:
current_subsequence_sum += numbers[j]
# Check if this subsequence sum is closer to the target
if abs(current_subsequence_sum - target) < abs(closest_sum - target):
closest_sum = current_subsequence_sum
return closest_sum
The key is to split the problem into two smaller, more manageable parts. Then, we cleverly combine results from each part to find the closest possible sum without checking every single option.
Here's how the algorithm would work step-by-step:
def closest_subsequence_sum(numbers, target):
def generate_all_sums(sub_array):
sums = {0}
for number in sub_array:
new_sums = set()
for current_sum in sums:
new_sums.add(current_sum + number)
sums.update(new_sums)
return sorted(list(sums))
length = len(numbers)
first_half = numbers[:length // 2]
second_half = numbers[length // 2:]
# Generate all possible subset sums for the first and second halves
first_half_sums = generate_all_sums(first_half)
second_half_sums = generate_all_sums(second_half)
closest_sum = float('inf')
# Iterate through sums of first half, finding closest match in second half.
for first_half_sum in first_half_sums:
left_index = 0
right_index = len(second_half_sums) - 1
while left_index <= right_index:
middle_index = (left_index + right_index) // 2
current_sum = first_half_sum + second_half_sums[middle_index]
if abs(current_sum - target) < abs(closest_sum - target):
closest_sum = current_sum
# Binary search: Adjust indices based on comparison to target.
if current_sum < target:
left_index = middle_index + 1
else:
right_index = middle_index - 1
# Return the closest sum found after considering all possibilities.
return closest_sum
Case | How to Handle |
---|---|
Empty input array | Return 0 as no subsequence sum can be calculated. |
Array with a single element | Return the value of the single element if its absolute difference with goal is smallest, otherwise 0 if goal is closer to 0. |
Array with all positive numbers and a negative target | Return 0, the closest possible sum. |
Array with all negative numbers and a positive target | Return 0, the closest possible sum. |
Large input array with numbers having a wide range of values (both positive and negative) | The algorithm needs to be efficient enough to avoid Time Limit Exceeded (TLE) errors; consider using dynamic programming or a meet-in-the-middle approach. |
Target is extremely large positive/negative number | The closest subsequence sum would likely be the sum of all positive/negative numbers respectively, and the algorithm should handle this without overflow. |
Integer overflow when calculating subsequence sums | Use a data type with a larger range (e.g., long) to store the subsequence sums, or check for potential overflows before performing the addition. |
Multiple subsequences with the same closest sum | The algorithm should arbitrarily return any one of them as per the problem statement, or specify that it returns one of the closest if the problem statement asked to return all. |