Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find closest subsequence sum in Python
Suppose we have an array nums and another value goal. We want to select a subsequence of nums such that the sum of its elements is the nearest to goal. In other words, if the sum of the subsequence's elements is s, then we want to minimize the absolute difference |s - goal|.
We have to find the minimum possible value of |s - goal|.
Example
If the input is nums = [8,-8,16,-1] and goal = -3, then the output will be 2 because we select the subsequence [8,-8,-1], with a sum of -1. The absolute difference is |-1 - (-3)| = |2| = 2, which is the minimum possible.
Algorithm Steps
To solve this problem, we follow these steps:
- Sort
numsbased on absolute values in descending order - Create prefix sum arrays for negative and positive remaining elements
- Use dynamic programming with pruning to explore all possible subsequence sums
- Track the minimum absolute difference from the goal
Implementation
def solve(nums, goal):
n = len(nums)
# Sort by absolute values in descending order for better pruning
nums.sort(key=lambda x: -abs(x))
# Precompute suffix sums for negative and positive values
neg = [0] * (n + 1) # Sum of negative values from index i onwards
pos = [0] * (n + 1) # Sum of positive values from index i onwards
for i in range(n - 1, -1, -1):
if nums[i] < 0:
neg[i] = neg[i + 1] + nums[i]
pos[i] = pos[i + 1]
else:
pos[i] = pos[i + 1] + nums[i]
neg[i] = neg[i + 1]
ans = abs(goal) # Initialize with distance from 0 to goal
current_sums = {0} # Set of all possible sums so far
def can_reach_goal(current_sum, remaining_neg, remaining_pos):
# Check if we can still reach within current best distance
min_possible = current_sum + remaining_neg
max_possible = current_sum + remaining_pos
return not (max_possible < goal - ans or goal + ans < min_possible)
# Process each number
for i in range(n):
# Filter sums that can still lead to better solutions
valid_sums = [x for x in current_sums if can_reach_goal(x, neg[i], pos[i])]
if not valid_sums:
break # No valid sums left, can't improve further
current_sums = set(valid_sums)
# For each valid sum, try including current number
for current_sum in valid_sums:
new_sum = current_sum + nums[i]
distance = abs(new_sum - goal)
if distance < ans:
ans = distance
if ans == 0:
return 0 # Found exact match
current_sums.add(new_sum)
return ans
# Test the function
nums = [8, -8, 16, -1]
goal = -3
result = solve(nums, goal)
print(f"Minimum distance: {result}")
Minimum distance: 2
How It Works
The algorithm uses dynamic programming with pruning:
- Sorting: Numbers are sorted by absolute value to enable better pruning
- Suffix Arrays: Pre-computed arrays track remaining positive and negative sums
- Pruning: At each step, we eliminate sums that cannot lead to better solutions
- State Tracking: We maintain all possible subsequence sums and update the minimum distance
Alternative Example
# Test with different input
nums = [1, 2, 3, 4, 5]
goal = 7
result = solve(nums, goal)
print(f"Array: {nums}")
print(f"Goal: {goal}")
print(f"Minimum distance: {result}")
print("Best subsequence could be [2, 5] with sum 7, distance = 0")
Array: [1, 2, 3, 4, 5] Goal: 7 Minimum distance: 0 Best subsequence could be [2, 5] with sum 7, distance = 0
Conclusion
This algorithm efficiently finds the closest subsequence sum using dynamic programming with pruning. The key insight is sorting by absolute values and using suffix sums to eliminate impossible branches early, achieving better performance than brute force enumeration.
