Subarray whose absolute sum is closest to K

Given an array of n elements and an integer K, the task is to find the subarray with minimum value of ||a[i] + a[i + 1] + ……. a[j]| – K|. In other words, find the contiguous sub-array whose sum of elements shows minimum deviation from K or the subarray whose absolute sum is closest to K.

Example

Input:: a[] = {1, 3, 7, 10}, K = 15
Output: Subarray {7, 10}
The contiguous sub-array [7, 10] shows minimum deviation of 2 from 15.

Input: a[] = {1, 2, 3, 4, 5, 6}, K = 6
Output: Subarray {1, 2, 3}
The contiguous sub-array [1, 2, 3] shows minimum deviation of 0 from 6.

A naive approach would be to check if the sum of each contiguous sub-array and it’s difference from K.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python Code to find sub-array whose 
# sum shows the minimum deviation
  
def getSubArray(arr, n, K):
    i = -1
    j = -1
    currSum = 0
    # starting index, ending index, Deviation
    result = [i, j, abs(K-abs(currSum))]
      
    # iterate i and j to get all subarrays
    for i in range(0, n):
          
        currSum = 0
          
        for j in range(i, n):
            currSum += arr[j]
            currDev = abs(K-abs(currSum))
              
            # found sub-array with less sum
            if (currDev < result[2]):
                result = [i, j, currDev]
                  
            # exactly same sum
            if (currDev == 0):
                return result
    return result
      
# Driver Code
def main():
    arr = [15, -3, 5, 2, 7, 6, 34, -6]
      
    n = len(arr)
      
    K = 50
      
    [i, j, minDev] = getSubArray(arr, n, K)
      
    if(i ==-1):
        print("The empty array shows minimum Deviation")
        return 0
      
    for i in range(i, j + 1): 
        print arr[i],
      
      
main()

chevron_right


Output:

-3 5 2 7 6 34

Time Complexity: O(N^2)

Efficient Approach: If the array only consists of non-negative integers, use the sliding window technique to improve the calculation time for sum in each iteration. The sliding window technique reduces the complexity by calculating the new sub-array sum using the previous sub-array sum. Increase the right index till the difference (K-sum) is greater than zero. The first sub-array with negative (K-sum) is considered, and the next sub-array is with left index = i+1(where i is the current right index).

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python Code to find non-negative 
# sub-array whose sum shows minimum deviation
# This works only if all elements
# in array are non-negative
  
  
# function to return the index 
def getSubArray(arr, n, K):
    currSum = 0
    prevDif = 0
    currDif = 0
    result = [-1, -1, abs(K-abs(currSum))]
    resultTmp = result
    i = 0
    j = 0
      
    while(i<= j and j<n):
          
        # Add Last element tp currSum
        currSum += arr[j]
          
        # Save Difference of previous Iteration
        prevDif = currDif
          
        # Calculate new Difference
        currDif = K - abs(currSum)
          
        # When the Sum exceeds K
        if(currDif <= 0):
            if abs(currDif) < abs(prevDif):
                  
            # Current Difference greater in magnitude
            # Store Temporary Result
                resultTmp = [i, j, currDif]
            else:
                  
            # Diffence in Previous was lesser
            # In previous, Right index = j-1
                resultTmp = [i, j-1, prevDif]
                  
            # In next iteration, Left Index Increases
            # but Right Index remains the Same
            # Update currSum and i Accordingly
            currSum -= (arr[i]+arr[j])
              
            i += 1
          
        # Case to simply increase Right Index
        else:
            resultTmp = [i, j, currDif]
            j += 1
              
        if(abs(resultTmp[2]) < abs(result[2])):
        # Check if lesser deviation found
            result = resultTmp
              
    return result
  
# Driver Code
def main():
    arr = [15, -3, 5, 2, 7, 6, 34, -6]
      
    n = len(arr)
      
    K = 50
      
    [i, j, minDev] = getSubArray(arr, n, K)
      
    if(i ==-1):
        print("The empty array shows minimum Deviation")
        return 0
      
    for i in range(i, j+1): 
        print arr[i],
      
      
main()

chevron_right


Output:

-3 5 2 7 6 34

Time Complexity: O(N)



My Personal Notes arrow_drop_up