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. So in other words, if the sum of the subsequence's elements is s, then we want to minimize the absolute difference |s - goal|.
So we have to find the minimum possible value of |s - goal|. So, if the input is like nums = [8,-8,16,-1] goal = -3, then the output will be 2 because select the subsequence [8,-8,-1], with a sum of -1. The absolute difference is |-1 - (-3)| = abs(2) = 2, this is the minimum.
To solve this, we will follow these steps −
n := size of nums
sort nums based on -ve value after getting absolute values of x
neg := make an array of size n+1 and fill with 0
pos := make an array of size n+1 and fill with 0
for i in range n-1 to 0, decrease by 1, do
if nums[i] < 0, then
neg[i] := neg[i+1] + nums[i]
pos[i] := pos[i+1]
otherwise,
pos[i] := pos[i+1] + nums[i]
neg[i] := neg[i+1]
ans := |goal|
s := a new set ans insert 0 into it
Define a function check() . This will take a, b
if b < goal - ans or goal + ans < a, then
return False
return True
From the main method, do the following
for i in range 0 to n - 1, do
sl := a list of x for all x in s when check(x+neg[i], x+pos[i] is true]
if size of sl is same as 0, then
come out from loop
s := a new set from sl
for each x in sl, do
y := x + nums[i]
if |y - goal| < ans, then
ans := |y - goal|
if ans is same as 0, then
return 0
insert y into s
return ans
Example
Let us see the following implementation to get better understanding
from collections import Counter def solve(nums, goal): n = len(nums) nums.sort(key=lambda x: -abs(x)) neg = [0 for _ in range(n+1)] pos = [0 for _ in range(n+1)] 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) s = set([0]) def check(a, b): if b < goal - ans or goal + ans < a: return False return True for i in range(n): sl = [x for x in s if check(x+neg[i], x+pos[i])] if len(sl) == 0: break s = set(sl) for x in sl: y = x + nums[i] if abs(y - goal) < ans: ans = abs(y - goal) if ans == 0: return 0 s.add(y) return ans nums = [8,-8,16,-1] goal = -3 print(solve(nums, goal))
Input
[0,1,2,3,4], [[3,1],[1,3],[5,6]]
Output
2