Skip to content
Related Articles

Related Articles

Sum of length of two smallest subsets possible from a given array with sum at least K

Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 25 May, 2021
Improve Article
Save Article

Given an array arr[] consisting of N integers and an integer K, the task is to find the sum of the length of the two smallest unique subsets having sum of its elements at least K.

Examples:

Input: arr[] = {2, 4, 5, 6, 7, 8}, K = 16
Output: 6
Explanation:
The subsets {2, 6, 8} and {4, 5, 7} are the two smallest subsets with sum K(= 16).
Therefore, the sum of the lengths of both these subsets = 3 + 3 = 6.

Input: arr[] = {14, 3, 7, 8, 9, 7, 12, 15, 10, 6}, K = 40
Output: 8

 

Approach: The given problem can be solved based on the following observations: 

  • Sorting the array reduces the problem to choosing a subarray whose sum is at least K between the range of indices [i, N], and then check, if the sum of the remaining array elements in the range of indices [i, N] is K or not.
  • To implement the above idea, a 2D array, say dp[][], is used such that dp[i][j] stores the minimum sum of the subset over the range of indices [i, N] having a value at least j. Then the transition state is similar to 0/1 Knapsack that can be defined as:
    • If the value of arr[i] is greater than j, then update dp[i][j] to arr[i].
    • Otherwise, update dp[i][j] to the minimum of dp[i + 1][j] and (dp[i + 1][j – arr[i]] + arr[i]).

Follow the steps below to solve the problem:

  • Sort the array in ascending order.
  • Initialize an array, say suffix[], and store the suffix sum of the array arr[] in it.
  • Initialize a 2D array, say dp[][], such that dp[i][j]  stores the minimum sum of the subset over the range of indices [i, N] having a value at least j.
  • Initialize dp[N][0] as 0 and all other states as INT_MAX.
  • Traverse the array arr[i] in reverse order and perform the following steps:
    • Iterate over the range of indices [0, K] in reverse order and perform the following operations:
      • If the value of arr[i] is at least j, then update the value of dp[i][j] as arr[i] as the current state has sum at least j. Now, continue the iteration.
      • If the value of next state, i.e., dp[i + 1][j – arr[i]] is INT_MAX, then update dp[i][j] as INT_MAX.
      • Otherwise, update dp[i][j] as the minimum of dp[i + 1][j] and (dp[i + 1][j – arr[i]] + arr[i]) to store the sum of all values having sum at least j.
  • Now, traverse the array suffix[] in reverse order and if the value of (suffix[i] – dp[i][K]) is at least K, then print (N – i) as the sum of the size of the two smallest subsets formed and break out of the loop.
  • Otherwise, print “-1”.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e9;
 
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
int MinimumLength(int A[], int N, int K)
{
    // Sort the array in ascending order
    sort(A, A + N);
 
    // Stores suffix sum of the array
    int suffix[N + 1] = { 0 };
 
    // Update the suffix sum array
    for (int i = N - 1; i >= 0; i--)
        suffix[i] = suffix[i + 1] + A[i];
 
    // Stores all dp-states
    int dp[N + 1][K + 1];
 
    // Initialize all dp-states
    // with a maximum possible value
    for (int i = 0; i <= N; i++)
        for (int j = 0; j <= K; j++)
            dp[i][j] = MAX;
 
    // Base Case
    dp[N][0] = 0;
 
    // Traverse the array arr[]
    for (int i = N - 1; i >= 0; i--) {
 
        // Iterate over the range [0, K]
        for (int j = K; j >= 0; j--) {
 
            // If A[i] is equal to at
            // least the required sum
            // j for the current state
            if (j <= A[i]) {
                dp[i][j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (dp[i + 1][j - A[i]] == MAX)
                dp[i][j] = MAX;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                dp[i][j] = min(dp[i + 1][j],
                               dp[i + 1][j - A[i]] + A[i]);
        }
    }
 
    // Traverse the suffix sum array
    for (int i = N - 1; i >= 0; i--) {
 
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - dp[i][K] >= K) {
 
            // Sum of lengths of the two
            // smallest subsets is obtained
            return N - i;
        }
    }
 
    // Return -1, if there doesn't
    // exist any subset of sum >= K
    return -1;
}
 
// Driver Code
int main()
{
    int arr[] = { 7, 4, 5, 6, 8 };
    int K = 13;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << MinimumLength(arr, N, K);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
static int MAX = (int)(1e9);
 
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
static int MinimumLength(int A[], int N, int K)
{
     
    // Sort the array in ascending order
    Arrays.sort(A);
     
    // Stores suffix sum of the array
    int suffix[] = new int[N + 1];
 
    // Update the suffix sum array
    for(int i = N - 1; i >= 0; i--)
        suffix[i] = suffix[i + 1] + A[i];
 
    // Stores all dp-states
    int dp[][] = new int[N + 1][K + 1];
 
    // Initialize all dp-states
    // with a maximum possible value
    for(int i = 0; i <= N; i++)
        for(int j = 0; j <= K; j++)
            dp[i][j] = MAX;
 
    // Base Case
    dp[N][0] = 0;
 
    // Traverse the array arr[]
    for(int i = N - 1; i >= 0; i--)
    {
         
        // Iterate over the range [0, K]
        for(int j = K; j >= 0; j--)
        {
             
            // If A[i] is equal to at
            // least the required sum
            // j for the current state
            if (j <= A[i])
            {
                dp[i][j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (dp[i + 1][j - A[i]] == MAX)
                dp[i][j] = MAX;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                dp[i][j] = Math.min(dp[i + 1][j],
                                    dp[i + 1][j - A[i]]
                                         + A[i]);
        }
    }
 
    // Traverse the suffix sum array
    for(int i = N - 1; i >= 0; i--)
    {
         
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - dp[i][K] >= K)
        {
             
            // Sum of lengths of the two
            // smallest subsets is obtained
            return N - i;
        }
    }
 
    // Return -1, if there doesn't
    // exist any subset of sum >= K
    return -1;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 7, 4, 5, 6, 8 };
    int K = 13;
    int N = arr.length;
 
    System.out.println(MinimumLength(arr, N, K));
}
}
 
// This code is contributed by Kingash


Python3




# Python3 program for the above approach
MAX = 1e9
 
# Function to calculate sum of lengths
# of two smallest subsets with sum >= K
def MinimumLength(A, N, K):
     
    # Sort the array in ascending order
    A.sort()
 
    # Stores suffix sum of the array
    suffix = [0] * (N + 1)
 
    # Update the suffix sum array
    for i in range(N - 1, -1, -1):
        suffix[i] = suffix[i + 1] + A[i]
 
    # Stores all dp-states
    dp = [[0] * (K + 1)] * (N + 1)
 
    # Initialize all dp-states
    # with a maximum possible value
    for i in range(N + 1):
        for j in range(K + 1):
            dp[i][j] = MAX
 
    # Base Case
    dp[N][0] = 0
 
    # Traverse the array arr[]
    for i in range(N - 1, -1, -1):
 
        # Iterate over the range [0, K]
        for j in range(K, -1, -1):
             
            # If A[i] is equal to at
            # least the required sum
            # j for the current state
            if (j <= A[i]) :
                dp[i][j] = A[i]
                continue
             
            # If the next possible
            # state doesn't exist
            if (dp[i + 1][j - A[i]] == MAX):
                dp[i][j] = MAX
 
            # Otherwise, update the current
            # state to the minimum of the
            # next state and state including
            # the current element A[i]
            else :
                dp[i][j] = min(dp[i + 1][j],
                               dp[i + 1][j - A[i]] + A[i])
         
    # Traverse the suffix sum array
    for i in range(N - 1, -1, -1):
 
        # If suffix[i] - dp[i][K] >= K
        if (suffix[i] - dp[i][K] >= K):
 
            # Sum of lengths of the two
            # smallest subsets is obtained
            return N - i
         
    # Return -1, if there doesn't
    # exist any subset of sum >= K
    return -1
 
# Driver Code
arr = [ 7, 4, 5, 6, 8 ]
K = 13
N = len(arr)
 
print(MinimumLength(arr, N, K))
 
# This code is contributed by splevel62


C#




// C# program for the above approach
using System;
 
class GFG{
 
static int MAX = (int)(1e9);
 
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
static int MinimumLength(int[] A, int N, int K)
{
     
    // Sort the array in ascending order
    Array.Sort(A);
 
    // Stores suffix sum of the array
    int[] suffix = new int[N + 1];
 
    // Update the suffix sum array
    for(int i = N - 1; i >= 0; i--)
        suffix[i] = suffix[i + 1] + A[i];
 
    // Stores all dp-states
    int[,] dp = new int[N + 1, K + 1];
 
    // Initialize all dp-states
    // with a maximum possible value
    for(int i = 0; i <= N; i++)
        for(int j = 0; j <= K; j++)
            dp[i, j] = MAX;
 
    // Base Case
    dp[N, 0] = 0;
 
    // Traverse the array arr[]
    for(int i = N - 1; i >= 0; i--)
    {
         
        // Iterate over the range [0, K]
        for(int j = K; j >= 0; j--)
        {
             
            // If A[i] is equal to at
            // least the required sum
            // j for the current state
            if (j <= A[i])
            {
                dp[i, j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (dp[i + 1, j - A[i]] == MAX)
                dp[i, j] = MAX;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                dp[i, j] = Math.Min(dp[i + 1, j],
                                    dp[i + 1, j - A[i]]
                                         + A[i]);
        }
    }
 
    // Traverse the suffix sum array
    for(int i = N - 1; i >= 0; i--)
    {
         
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - dp[i, K] >= K)
        {
             
            // Sum of lengths of the two
            // smallest subsets is obtained
            return N - i;
        }
    }
 
    // Return -1, if there doesn't
    // exist any subset of sum >= K
    return -1;
}
 
// Driver Code
public static void Main(string[] args)
{
    int[] arr = { 7, 4, 5, 6, 8 };
    int K = 13;
    int N = arr.Length;
 
    Console.WriteLine(MinimumLength(arr, N, K));
}
}
 
// This code is contributed by ukasp


Javascript




<script>
 
// javascript program for the above approach
var max1 = 1000000000;
 
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
function MinimumLength(A, N, K)
{
0
    // Sort the array in ascending order
    A.sort();
 
    // Stores suffix sum of the array
    var suffix = Array(N + 1).fill(0);
     
    var i;
    // Update the suffix sum array
    for (i = N - 1; i >= 0; i--)
        suffix[i] = suffix[i + 1] + A[i];
 
    // Stores all dp-states
    var dp = new Array(N + 1);
    for (i = 0; i < N+1; i++)
       dp[i] = new Array(K + 1);
 
    // Initialize all dp-states
    // with a max1imum possible value
    var j;
    for (i = 0; i <= N; i++) {
        for (j = 0; j <= K; j++){
            dp[i][j] = max1;
        }
    };
 
    // Base Case
    dp[N][0] = 0;
 
    // Traverse the array arr[]
    for (i = N - 1; i >= 0; i--) {
 
        // Iterate over the range [0, K]
        for (j = K; j >= 0; j--) {
 
            // If A[i] is equal to at
            // least the required sum
            // j for the current state
            if (j <= A[i]) {
                dp[i][j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (dp[i + 1][j - A[i]] == max1)
                dp[i][j] = max1;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                dp[i][j] = Math.min(dp[i + 1][j],
                               dp[i + 1][j - A[i]] + A[i]);
        }
    }
 
    // Traverse the suffix sum array
    for (i = N - 1; i >= 0; i--) {
 
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - dp[i][K] >= K) {
 
            // Sum of lengths of the two
            // smallest subsets is obtained
            return N - i;
        }
    }
 
    // Return -1, if there doesn't
    // exist any subset of sum >= K
    return -1;
}
 
// Driver Code
 
    var arr = [7, 4, 5, 6, 8];
    var K = 13;
    var N = arr.length;
 
    document.write(MinimumLength(arr, N, K));
 
// This code is contributed by SURENDRA_GANGWAR.
</script>


Output: 

4

 

Time Complexity: O(N * K)
Auxiliary Space: O(N * K)

 


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!