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. 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

Updated on: 08-Oct-2021

323 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements