hard Closest Subsequence Sum
Problem Statement
Given an integer array nums and an integer goal, find a subsequence of nums such that the sum of its elements is as close as possible to goal.
In other words, if the sum of the subsequence's elements is sum, then you need to minimize the absolute difference abs(sum - goal).
Return the minimum possible value of abs(sum - goal).
A subsequence is formed by removing some elements (possibly all or none) from the original array.
Examples
Example 1:
- Input: nums =
[1, 2, 3, 1, 1], goal =6 - Expected Output:
0 - Explanation: The subsequence
[1, 2, 3],[2, 3, 1]or[1, 3, 1, 1]has a sum of6, which matches thegoal. The absolute difference is0.
Example 2:
- Input: nums =
[1, 2, 9, -6, 15], goal =7 - Expected Output:
1 - Explanation: The subsequence
[1, 2, 9, -6]has a sum of6, which is closest togoal. The absolute difference is1.
Example 3:
- Input: nums =
[1, 2, 4, 5], goal =-1 - Expected Output:
1 - Explanation: The subsequence
[](empty subsequence) has a sum of0, which exactly matches thegoal. The absolute difference is1.
Constraints:
- 1 <= nums.length <= 40
- -107 <= nums[i] <= 107
- -109 <= goal <= 109
Try it yourself
Try solving this question here:
✅ Solution Closest Subsequence Sum
Problem Statement
Given an integer array nums and an integer goal, find a subsequence of nums such that the sum of its elements is as close as possible to goal.
In other words, if the sum of the subsequence's elements is sum, then you need to minimize the absolute difference abs(sum - goal).
Return the minimum possible value of abs(sum - goal).
A subsequence is formed by removing some elements (possibly all or none) from the original array.
Examples
Example 1:
- Input: nums =
[1, 2, 3, 1, 1], goal =6 - Expected Output:
0 - Explanation: The subsequence
[1, 2, 3],[2, 3, 1]or[1, 3, 1, 1]has a sum of6, which matches thegoal. The absolute difference is0.
Example 2:
- Input: nums =
[1, 2, 9, -6, 15], goal =7 - Expected Output:
1 - Explanation: The subsequence
[1, 2, 9, -6]has a sum of6, which is closest togoal. The absolute difference is1.
Example 3:
- Input: nums =
[1, 2, 4, 5], goal =-1 - Expected Output:
1 - Explanation: The subsequence
[](empty subsequence) has a sum of0, which exactly matches thegoal. The absolute difference is1.
Constraints:
- 1 <= nums.length <= 40
- -107 <= nums[i] <= 107
- -109 <= goal <= 109
Solution
To solve this problem, we use the "Meet in the Middle" approach. This strategy is effective because it splits the problem into two smaller subproblems, which makes it easier to manage and compute all possible subsequence sums.
The first step involves generating all possible subsequence sums for both halves of the array. We then sort the sums from one half to enable fast lookup using binary search. For each sum from the first half, we calculate the difference between the goal and that sum, then find the closest matching sum from the sorted list of sums from the other half. By minimizing this difference, we find the sum that is closest to the goal. This approach significantly reduces the problem's complexity by leveraging binary search on a sorted array of subsequence sums.
Step-by-Step Algorithm
-
Divide the Array:
- Split the array
numsinto two halves. - Store the first half in an array called
leftand the second half in an array calledright.
- Split the array
-
Generate Subsequences Sums for Each Half:
- For each half (
leftandright), generate all possible sums of their subsequences. - To do this, iterate through all possible binary representations of numbers up to
2^(size of half). For each binary number, add the corresponding elements in the half to the sum if the corresponding bit is set. - Store the sums for the
lefthalf in a list calledleftSumsand for therighthalf in a list calledrightSums.
- For each half (
-
Sort the Sums from the Right Half:
- Sort the list
rightSumsto enable efficient binary search later.
- Sort the list
-
Initialize Minimum Difference:
- Initialize a variable
minDiffto store the minimum absolute difference found. Set it to a large value (e.g.,Integer.MAX_VALUE).
- Initialize a variable
-
Find the Closest Sum to the Goal:
- For each sum in
leftSums, calculate the target differencetargetby subtracting the sum from the goal. - First, update
minDiffby comparing the currentminDiffwith the absolute value oftarget(this accounts for the case where the subsequence is from the left half only). - Use binary search on
rightSumsto find the closest possible sum that would make the sum of both halves as close as possible to the goal.
- For each sum in
-
Binary Search and Handle Non-Exact Matches:
- If the binary search does not find an exact match, the
Collections.binarySearch()method returns a negative index. This negative index can be used to identify where the target would be inserted in the sorted list to maintain order. - Convert the negative index
idxto a positive index by calculatingidx = -idx - 1. This index now points to the first element inrightSumsthat is greater than the target. - Check the Closest Larger Value:
- If
idxis less than the size ofrightSums, compare the absolute difference between the target and the sum at this index (rightSums.get(idx)). UpdateminDiffif this difference is smaller than the currentminDiff.
- If
- Check the Closest Smaller Value:
- If
idxis greater than0, it means there is a value inrightSumsthat is smaller than the target. Compare the absolute difference between the target and the sum atrightSums.get(idx - 1). Again, updateminDiffif this difference is smaller.
- If
- If the binary search does not find an exact match, the
-
Return the Minimum Difference:
- After evaluating all possible subsequence sums, return
minDiffas the closest difference between any subsequence sum and the goal.
- After evaluating all possible subsequence sums, return
Algorithm Walkthrough
Let's walk through the expanded explanation for the key step using the example nums = [1, 2, 3, 1, 1] and goal = 6.
-
Divide the Array:
- Split
numsinto:left = [1, 2]right = [3, 1, 1]
- Split
-
Generate Subsequences Sums:
- For
left:- Possible subsequences:
[],[1],[2],[1, 2] - Corresponding sums:
0,1,2,3 leftSums = [0, 1, 2, 3]
- Possible subsequences:
- For
right:- Possible subsequences:
[],[3],[1],[1],[3, 1],[3, 1],[1, 1],[3, 1, 1] - Corresponding sums:
0,3,1,1,4,4,2,5 rightSums = [0, 1, 1, 2, 3, 4, 4, 5](after sorting)
- Possible subsequences:
- For
-
Initialize Minimum Difference:
- Set
minDiff = Integer.MAX_VALUE
- Set
-
Find the Closest Sum to the Goal:
- For
sum = 0inleftSums, calculatetarget = 6 - 0 = 6.
- For
-
Binary Search and Handle Non-Exact Matches:
- Perform binary search on
rightSumsfortarget = 6. - The search does not find an exact match, returning
idx = -9(indicating where6would be inserted to keep the list sorted). - Convert
idxto a positive index:idx = -idx - 1 = 8. - Check the Closest Larger Value:
idx = 8is equal to the size ofrightSums, so we skip this check (no element larger thantarget).
- Check the Closest Smaller Value:
- Since
idx > 0, checkrightSums.get(7), which is5. - Calculate the difference:
abs(6 - 5) = 1. - Update
minDiffto1.
- Since
- Perform binary search on
-
Continue Checking Other Sums:
- For
sum = 1inleftSums, calculatetarget = 6 - 1 = 5. - Binary search on
rightSumsfinds an exact match5at index7, so return0immediately.
- For
Code
import java.util.*;
public class Solution {
// Method to find the closest subsequence sum to the goal
public int minAbsDifference(int[] nums, int goal) {
// Divide the array into two halves
int n = nums.length;
int[] left = Arrays.copyOfRange(nums, 0, n / 2);
int[] right = Arrays.copyOfRange(nums, n / 2, n);
// Generate all possible sums for both halves
List<Integer> leftSums = generateSubsequenceSums(left);
List<Integer> rightSums = generateSubsequenceSums(right);
// Sort the right half sums for binary search
Collections.sort(rightSums);
int minDiff = Integer.MAX_VALUE;
// Compare each sum from the left half with the closest sum from the right half
for (int sum : leftSums) {
int target = goal - sum;
minDiff = Math.min(minDiff, Math.abs(target)); // Compare with 0 (empty subsequence)
int idx = Collections.binarySearch(rightSums, target);
if (idx >= 0) {
return 0; // If exact match is found
}
// If no exact match, find the closest values
idx = -idx - 1;
if (idx < rightSums.size()) {
minDiff = Math.min(minDiff, Math.abs(target - rightSums.get(idx)));
}
if (idx > 0) {
minDiff = Math.min(minDiff, Math.abs(target - rightSums.get(idx - 1)));
}
}
return minDiff;
}
// Method to generate all possible sums of subsequences for a given array
private List<Integer> generateSubsequenceSums(int[] nums) {
List<Integer> result = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < (1 << n); i++) {
int sum = 0;
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) != 0) {
sum += nums[j];
}
}
result.add(sum);
}
return result;
}
public static void main(String[] args) {
Solution solution = new Solution();
// Test case 1
int[] nums1 = { 1, 2, 3, 1, 1 };
int goal1 = 6;
System.out.println(
"Actual Output: " + solution.minAbsDifference(nums1, goal1)
);
// Test case 2
int[] nums2 = { 1, 2, 9, -6, 15 };
int goal2 = 7;
System.out.println(
"Actual Output: " + solution.minAbsDifference(nums2, goal2)
);
// Test case 3
int[] nums3 = { 1, 2, 4, 5 };
int goal3 = -1;
System.out.println(
"Actual Output: " + solution.minAbsDifference(nums3, goal3)
);
}
}
Complexity Analysis
Time Complexity
-
Generating Subsequences Sums:
- For each half of the array, we generate all possible sums of subsequences. Since there are 2(n/2) subsequences for an array of size
n/2, the time complexity for generating these sums is O(2(n/2) * (n/2)).
- For each half of the array, we generate all possible sums of subsequences. Since there are 2(n/2) subsequences for an array of size
-
Sorting the Right Half Sums:
- Sorting the sums of the right half takes O(2(n/2) * log(2(n/2)).
-
Binary Search:
- For each sum in the left half (2(n/2) sums), we perform a binary search on the sorted list of sums from the right half. The time complexity for this step is O(2(n/2)) * log(2(n/2))).
Combining all these steps, the overall time complexity of the algorithm is: O(2(n/2) * (n/2) + 2(n/2) * log(2(n/2))) This simplifies to: O(n * 2(n/2))
Space Complexity
- The space complexity is mainly due to storing the subsequence sums for both halves of the array, which requires O(2(n/2)) space for each half. Hence, the overall space complexity is: O(2(n/2))
🤖 Don't fully get this? Learn it with Claude
Stuck on Closest Subsequence Sum? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Closest Subsequence Sum** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Closest Subsequence Sum** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Closest Subsequence Sum**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Closest Subsequence Sum**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.