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:
- 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.
- Iterate over the range of indices [0, K] in reverse order and perform the following operations:
- 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> |
4
Time Complexity: O(N * K)
Auxiliary Space: O(N * K)