Open In App

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

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: 

Follow the steps below to solve the problem:

Below is the implementation of the above approach:




// 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 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 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# 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




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

 Efficient Approach : using array instead of 2d matrix to optimize space complexity

In previous code we can se that dp[i][j] is dependent upon dp[i+1][j-1] or dp[i][j-1] so we can assume that dp[i+1] is next and dp[i] is current row.

Implementations Steps :

Implementation :




// 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];
 
 
 
    // Initialize all dp-states
    // with a maximum possible value
    vector<int>curr(K+1 , MAX);
    vector<int>next(K+1 , MAX);
 
    // Base Case
    curr[0] = 0;
    next[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]) {
                curr[j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (next[j - A[i]] == MAX)
                curr[j] = MAX;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                curr[j] = min(next[j],
                            next[j - A[i]] + A[i]);
        }
        next = curr;
    }
 
    // Traverse the suffix sum array
    for (int i = N - 1; i >= 0; i--) {
 
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - curr[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;
}
// this code is contributed by bhardwajji




import java.util.Arrays;
 
public class Main {
  static final 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];
 
    // Initialize all dp-states
    // with a maximum possible value
    int[] curr = new int[K + 1];
    Arrays.fill(curr, MAX);
    int[] next = new int[K + 1];
    Arrays.fill(next, MAX);
 
    // Base Case
    curr[0] = 0;
    next[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 (j <= A[i]) {
          curr[j] = A[i];
          continue;
        }
 
        // If the next possible
        // state doesn't exist
        if (next[j - A[i]] == MAX)
          curr[j] = MAX;
 
        else
          curr[j] = Math.min(next[j],
                             next[j - A[i]] + A[i]);
      }
      next = curr.clone();
    }
 
    // Traverse the suffix sum array
    for (int i = N - 1; i >= 0; i--) {
 
      // If suffix[i] - dp[i][K] >= K
      if (suffix[i] - curr[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;
  }
 
  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));
  }
}




const MAX = 1e9;
 
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
function MinimumLength(A, N, K) {
    // Sort the array in ascending order
    A.sort((a, b) => a - b);
 
    // Stores suffix sum of the array
    let suffix = Array(N + 1).fill(0);
 
    // Update the suffix sum array
    for (let i = N - 1; i >= 0; i--)
        suffix[i] = suffix[i + 1] + A[i];
 
    // Initialize all dp-states
    // with a maximum possible value
    let curr = Array(K + 1).fill(MAX);
    let next = Array(K + 1).fill(MAX);
 
    // Base Case
    curr[0] = 0;
    next[0] = 0;
 
    // Traverse the array arr[]
    for (let i = N - 1; i >= 0; i--) {
        // Iterate over the range [0, K]
        for (let 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]) {
                curr[j] = A[i];
                continue;
            }
 
            // If the next possible
            // state doesn't exist
            if (next[j - A[i]] == MAX)
                curr[j] = MAX;
 
            // Otherwise, update the current
            // state to the minimum of the
            // next state and state including
            // the current element A[i]
            else
                curr[j] = Math.min(next[j],
                            next[j - A[i]] + A[i]);
        }
        next = [...curr];
    }
 
    // Traverse the suffix sum array
    for (let i = N - 1; i >= 0; i--) {
        // If suffix[i] - dp[i][K] >= K
        if (suffix[i] - curr[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
let arr = [7, 4, 5, 6, 8];
let K = 13;
let N = arr.length;
 
console.log(MinimumLength(arr, N, K));




import sys
MAX = sys.maxsize
 
# 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]
 
    # Initialize all dp-states
    # with a maximum possible value
    curr = [MAX] * (K+1)
    next_ = [MAX] * (K+1)
 
    # Base Case
    curr[0] = 0
    next_[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]:
                curr[j] = A[i]
                continue
 
            # If the next possible
            # state doesn't exist
            if next_[j - A[i]] == MAX:
                curr[j] = MAX
 
            # Otherwise, update the current
            # state to the minimum of the
            # next state and state including
            # the current element A[i]
            else:
                curr[j] = min(next_[j],
                              next_[j - A[i]] + A[i])
        next_ = curr.copy()
 
    # Traverse the suffix sum array
    for i in range(N - 1, -1, -1):
 
        # If suffix[i] - dp[i][K] >= K
        if suffix[i] - curr[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
if __name__ == "__main__":
    arr = [7, 4, 5, 6, 8]
    K = 13
    N = len(arr)
 
    print(MinimumLength(arr, N, K))




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    static int MAX = 1000000000;
 
    // 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];
 
        // Initialize all dp-states
        // with a maximum possible value
        List<int> curr = new List<int>(Enumerable.Repeat(MAX, K + 1));
        List<int> next = new List<int>(Enumerable.Repeat(MAX, K + 1));
 
        // Base Case
        curr[0] = 0;
        next[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])
                {
                    curr[j] = A[i];
                    continue;
                }
 
                // If the next possible
                // state doesn't exist
                if (next[j - A[i]] == MAX)
                    curr[j] = MAX;
 
                // Otherwise, update the current
                // state to the minimum of the
                // next state and state including
                // the current element A[i]
                else
                    curr[j] = Math.Min(next[j], next[j - A[i]] + A[i]);
            }
            next = new List<int>(curr);
        }
 
        // Traverse the suffix sum array
        for (int i = N - 1; i >= 0; i--)
        {
            // If suffix[i] - dp[i][K] >= K
            if (suffix[i] - curr[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()
    {
        int[] arr = { 7, 4, 5, 6, 8 };
        int K = 13;
        int N = arr.Length;
 
        Console.WriteLine(MinimumLength(arr, N, K));
    }
}

Output
4

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


Article Tags :