Open In App

Optimally accommodate 0s and 1s from a Binary String into K buckets

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a binary string S, consisting of 0’s and 1’s. You have to accommodate the 0’s and 1’s into the K buckets in such a way that the following conditions are satisfied: 

  1. You fill the 0’s and 1’s into the buckets preserving the relative order of 0’s and 1’s. For example, you cannot put S[1] into bucket 2 and S[0] into bucket 1. You have to preserve the original ordering of the binary string.
  2. No bucket should be left empty and no element in the string should be left unaccommodated.
  3. The sum of all the products of (number of 0’s * number of 1’s) for each bucket should be the minimum among all possible accommodation arrangements.

If a solution is not possible, then print -1.

Examples:  

Input: S = "0001", K = 2
Output: 0
We have 3 choices {"0", "001"}, {"00", "01"}, {"000", 1}
First choice, we will get 1*0 + 2*1 = 2
Second choice, we will get 2*0 + 1*1 = 1
Third choice, we will get 3*0 + 0*1 = 0
Out of all the 3 choices, the third choice
is giving the minimum answer.
Input: S = "0101", K = 1
Output: 1

Recursive implementation: You have to accommodate binary string into K buckets without disturbing the above conditions. Then simple recursive solution can be made by first filling up i-th bucket (starting from 0) by putting elements from start to N (N = length of binary string) and keep adding count zeroes and ones till start index. For each iteration, if there x zeroes and y ones till start then recur for f(start, K) = x * y + f(start + 1, K – 1) because next accommodation will be made from (start + 1)-th index and remaining buckets will K – 1. 

So, the recursive formula will be – 

F(start, current_bucket) =  |           |
| min | F(i + 1, next_bucket) + (ones * zeroes in current_bucket)
| |
| i = start to N

Top-Down Dynamic Approach: 
The recursive relation can be changed to Dynamic Solution by saving the results of different combinations of start and bucket variable into 2-D DP array. We can use the fact that the order of the string should be preserved. You can have a 2-D array saving the states of size [size of string * buckets], where dp[i][j] will tell us minimum value of accommodation till i’th index of the string using j + 1 buckets. Our final answer will be in dp[N-1][K-1]

Below is the implementation of the above approach:  

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
vector<vector<int> > dp;
 
// Function to find the minimum required
// sum using dynamic programming
int solveUtil(int start, int bucket, string str, int K)
{
    int N = str.size();
 
    // If both start and bucket reached end then
    // return 0 else that arrangement is not possible
    // so return INT_MAX
    if (start == N) {
        if (bucket == K)
            return 0;
        return INT_MAX;
    }
 
    // Corner case
    if (bucket == K)
        return INT_MAX;
 
    // If state if already calculated
    // then return its answer
    if (dp[start][bucket] != -1)
        return dp[start][bucket];
 
    int zeroes = 0;
    int ones = 0;
    int ans = INT_MAX;
 
    // Start filling zeroes and ones which to be accommodated
    // in jth bucket then ans for current arrangement will be
    // ones*zeroes + recur(i+1, bucket+1)
    for (int i = start; i < N; ++i) {
        if (str[i] == '1')
            ones++;
        else
            zeroes++;
 
        if (ones * zeroes > ans)
            break;
 
        int temp = solveUtil(i + 1, bucket + 1, str, K);
 
        // If this arrangement is not possible then
        // don't calculate further
        if (temp != INT_MAX) {
            ans = min(ans, temp + (ones * zeroes));
        }
    }
 
    return dp[start][bucket] = ans;
}
 
// Function to initialize the dp and call
// solveUtil() method to get the answer
int solve(string str, int K)
{
    int N = str.size();
    dp.clear();
    dp.resize(N, vector<int>(K, -1));
 
    // Start with 0-th index and 1 bucket
    int ans = solveUtil(0, 0, str, K);
 
    return ans == INT_MAX ? -1 : ans;
}
 
// Driver code
int main()
{
    string S = "0101";
 
    // K buckets
    int K = 2;
 
    cout << solve(S, K) << endl;
 
    return 0;
}


Java




// Java implementation of the approach
import java.io.*;
import java.util.*;
 
class GFG{
 
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
static int[][] dp;
 
// Function to find the minimum required
// sum using dynamic programming
static int solveUtil(int start, int bucket,
                     String str, int K)
{
    int N = str.length();
     
    // If both start and bucket reached end
    // then return 0 else that arrangement
    // is not possible so return INT_MAX
    if (start == N)
    {
        if (bucket == K)
        {
            return 0;
        }
        return Integer.MAX_VALUE;
    }
     
    // Corner case
    if (bucket == K)
    {
        return Integer.MAX_VALUE;
    }
     
    // If state if already calculated
    // then return its answer
    if (dp[start][bucket] != -1)
    {
        return dp[start][bucket];
    }
    int zeroes = 0;
    int ones = 0;
    int ans = Integer.MAX_VALUE;
     
    // Start filling zeroes and ones which to be
    // accommodated in jth bucket then ans for
    // current arrangement will be
    // ones*zeroes + recur(i+1, bucket+1)
    for(int i = start; i < N; ++i)
    {
        if (str.charAt(i) == '1')
        {
            ones++;
        }
        else
        {
            zeroes++;
        }
        if (ones * zeroes > ans)
        {
            break;
        }
        int temp = solveUtil(i + 1, bucket + 1, str, K);
         
        // If this arrangement is not possible then
        // don't calculate further
        if (temp != Integer.MAX_VALUE)
        {
            ans = Math.min(ans, temp + (ones * zeroes));
        }
    }
    return dp[start][bucket] = ans;
}
 
// Function to initialize the dp and call
// solveUtil() method to get the answer
static int solve(String str, int K)
{
    int N = str.length();
    dp = new int[N][K];
     
    for(int[] row : dp)
    {
        Arrays.fill(row, -1);
    }
     
    // Start with 0-th index and 1 bucket
    int ans = solveUtil(0, 0, str, K);
    return ans == Integer.MAX_VALUE ? -1 : ans;
}
 
// Driver code
public static void main(String[] args)
{
    String S = "0101";
     
    // K buckets
    int K = 2;
     
    System.out.println(solve(S, K));
}
}
 
// This code is contributed by rag2127


Python3




# Python3 implementation of the approach
 
# 2-D dp array saving different states
# dp[i][j] = minimum value of accommodation
# till i'th index of the string
# using j+1 number of buckets.
 
# Function to find the minimum required
# sum using dynamic programming
def solveUtil(start, bucket, str1, K,dp):
 
    N = len(str1)
 
    # If both start and bucket reached end then
    # return 0 else that arrangement is not possible
    # so return INT_MAX
    if (start == N) :
        if (bucket == K):
            return 0
        return 10**9
 
 
    # Corner case
    if (bucket == K):
        return 10**9
 
    # If state if already calculated
    # then return its answer
    if (dp[start][bucket] != -1):
        return dp[start][bucket]
 
    zeroes = 0
    ones = 0
    ans = 10**9
 
    # Start filling zeroes and ones which to be accommodated
    # in jth bucket then ans for current arrangement will be
    # ones*zeroes + recur(i+1, bucket+1)
    for i in range(start,N):
        if (str1[i] == '1'):
            ones += 1
        else:
            zeroes += 1
 
        if (ones * zeroes > ans):
            break
 
        temp = solveUtil(i + 1, bucket + 1, str1, K,dp)
 
        # If this arrangement is not possible then
        # don't calculate further
        if (temp != 10**9):
            ans = min(ans, temp + (ones * zeroes))
 
    dp[start][bucket] = ans
 
    return ans
 
 
# Function to initialize the dp and call
# solveUtil() method to get the answer
def solve(str1, K):
 
    N = len(str1)
 
    dp = [[-1 for i in range(K)] for i in range(N)]
 
    # Start with 0-th index and 1 bucket
    ans = solveUtil(0, 0, str1, K,dp)
 
    if ans == 10**9:
        return -1
    else:
        return ans
 
 
# Driver code
 
s = "0101"
S=[i for i in s]
 
# K buckets
K = 2
 
print(solve(S, K))
 
# This code is contributed by mohit kumar 29


C#




// C# implementation of the approach
using System;
class GFG
{
     
    // 2-D dp array saving different states
    // dp[i][j] = minimum value of accommodation
    // till i'th index of the string
    // using j+1 number of buckets.
    static int[,] dp;
      
    // Function to find the minimum required
    // sum using dynamic programming
    static int solveUtil(int start, int bucket,
                         string str, int K)
    {
        int N = str.Length;
          
        // If both start and bucket reached end
        // then return 0 else that arrangement
        // is not possible so return INT_MAX
        if (start == N)
        {
            if (bucket == K)
            {
                return 0;
            }
            return Int32.MaxValue;
        }
          
        // Corner case
        if (bucket == K)
        {
            return Int32.MaxValue;
        }
          
        // If state if already calculated
        // then return its answer
        if (dp[start,bucket] != -1)
        {
            return dp[start, bucket];
        }
        int zeroes = 0;
        int ones = 0;
        int ans = Int32.MaxValue;
          
        // Start filling zeroes and ones which to be
        // accommodated in jth bucket then ans for
        // current arrangement will be
        // ones*zeroes + recur(i+1, bucket+1)
        for(int i = start; i < N; ++i)
        {
            if (str[i] == '1')
            {
                ones++;
            }
            else
            {
                zeroes++;
            }
            if (ones * zeroes > ans)
            {
                break;
            }
            int temp = solveUtil(i + 1, bucket + 1, str, K);
              
            // If this arrangement is not possible then
            // don't calculate further
            if (temp != Int32.MaxValue)
            {
                ans = Math.Min(ans, temp + (ones * zeroes));
            }
        }
        return dp[start, bucket] = ans;
    }
      
    // Function to initialize the dp and call
    // solveUtil() method to get the answer
    static int solve(string str, int K)
    {
        int N = str.Length;
        dp = new int[N, K];       
        for(int i = 0; i < N; i++)
        {
            for(int j = 0; j < K; j++)
            {
                dp[i, j] = -1;
            }
        }
          
        // Start with 0-th index and 1 bucket
        int ans = solveUtil(0, 0, str, K);
        return ans == Int32.MaxValue ? -1 : ans;
    }
 
  // Driver code
  static void Main()
  {
    string S = "0101";
      
    // K buckets
    int K = 2;
      
    Console.WriteLine(solve(S, K));
  }
}
 
// This code is contributed by divyeshrabadiya07.


Javascript




<script>
 
// Javascript implementation of the approach
 
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
let dp;
 
// Function to find the minimum required
// sum using dynamic programming
function solveUtil(start, bucket, str, K)
{
    let N = str.length;
      
    // If both start and bucket reached end
    // then return 0 else that arrangement
    // is not possible so return INT_MAX
    if (start == N)
    {
        if (bucket == K)
        {
            return 0;
        }
        return Number.MAX_VALUE;
    }
      
    // Corner case
    if (bucket == K)
    {
        return Number.MAX_VALUE;
    }
      
    // If state if already calculated
    // then return its answer
    if (dp[start][bucket] != -1)
    {
        return dp[start][bucket];
    }
    let zeroes = 0;
    let ones = 0;
    let ans = Number.MAX_VALUE;
      
    // Start filling zeroes and ones which to be
    // accommodated in jth bucket then ans for
    // current arrangement will be
    // ones*zeroes + recur(i+1, bucket+1)
    for(let i = start; i < N; ++i)
    {
        if (str[i] == '1')
        {
            ones++;
        }
        else
        {
            zeroes++;
        }
        if (ones * zeroes > ans)
        {
            break;
        }
        let temp = solveUtil(i + 1, bucket + 1, str, K);
          
        // If this arrangement is not possible then
        // don't calculate further
        if (temp != Number.MAX_VALUE)
        {
            ans = Math.min(ans, temp + (ones * zeroes));
        }
    }
    return dp[start][bucket] = ans;
}
 
// Function to initialize the dp and call
// solveUtil() method to get the answer
function solve(str, K)
{
    let N = str.length;
    dp = new Array(N);
    for(let i = 0; i < N; i++)
    {
        dp[i] = new Array(K);
        for(let j = 0; j < K; j++)
        {
            dp[i][j] = -1;
        }
    }
     
    // Start with 0-th index and 1 bucket
    let ans = solveUtil(0, 0, str, K);
    return ans == Number.MAX_VALUE ? -1 : ans;
}
 
// Driver code
let  S = "0101";
      
// K buckets
let K = 2;
      
document.write(solve(S, K));
 
// This code is contributed by unknown2108
 
</script>


Output

2



Time Complexity: O(N3
Space Complexity: O(N2)

This solution is still not optimised because it calls the same state a number of times. So, now look into the Optimised Bottom Up DP Approach.

Bottom-Up Dynamic Approach: Let us try to think about the final state first. Here the variables are the number of buckets and the index of the string. Let dp[i][j] be the minimum sum of products for string elements 0 to j-1 and i buckets. Now to define our transition function, we will have to start from the back and consider partition at each possible position k. Hence our transition function looks like:  

dp [i][j] = for all k = 0 to j min(dp[i][k-1] + numberOfZeroes * numberOfOnes)
for i = 0 (single partition) simple count number of 0's and 1's and do the multiplication.
And if number of buckets is more than string length till now ans is -1 as we cant fill all
the available buckets.

Below is the implementation of the above approach: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum required
// sum using dynamic programming
int solve(string str, int K)
{
    int n = str.length();
 
    // dp[i][j] = minimum val of accommodation
    // till j'th index of the string
    // using i+1 number of buckets.
    // Final ans will be in dp[n-1][K-1]
    long long dp[K][n];
 
    // Initialise dp with all states as 0
    memset(dp, 0, sizeof dp);
 
    // Corner cases
    if (n < K)
        return -1;
    else if (n == K)
        return 0;
 
    // Filling first row, if only 1 bucket then simple count
    // number of zeros and ones and do the multiplication
    long long zeroes = 0, ones = 0;
 
    for (int i = 0; i < n; i++) {
        if (str[i] == '0')
            zeroes++;
        else
            ones++;
 
        dp[0][i] = ones * zeroes;
    }
 
    for (int s = 1; s < K; s++) {
        for (int i = 0; i < n; i++) {
 
            dp[s][i] = INT_MAX;
 
            ones = 0;
            zeroes = 0;
            for (int k = i; k >= 0; k--) {
                if (str[k] == '0')
                    zeroes++;
                else
                    ones++;
 
                // If k = 0 then this arrangement is not possible
                dp[s][i] = min(dp[s][i],
                               +((k - 1 >= 0)
                                     ? ones * zeroes + dp[s - 1][k - 1]
                                     : INT_MAX));
            }
        }
    }
 
    // If no arrangement is possible then
    // our answer will remain INT_MAX so return -1
    return (dp[K - 1][n - 1] == INT_MAX) ? -1 : dp[K - 1][n - 1];
}
 
// Driver code
int main()
{
    string S = "0101";
 
    // K buckets
    int K = 2;
 
    cout << solve(S, K) << endl;
 
    return 0;
}


Java




// Java implementation of the approach
 
class GFG
{
    // Function to find the minimum required
    // sum using dynamic programming
    static long solve(String str, int K)
    {
        int n = str.length();
     
        // dp[i][j] = minimum val of accommodation
        // till j'th index of the string
        // using i+1 number of buckets.
        // Final ans will be in dp[n-1][K-1]
        long dp[][] = new long[K][n];
     
     
        // Corner cases
        if (n < K)
            return -1;
        else if (n == K)
            return 0;
     
        // Filling first row, if only 1 bucket then simple count
        // number of zeros and ones and do the multiplication
        long zeroes = 0, ones = 0;
     
        for (int i = 0; i < n; i++)
        {
            if (str.charAt(i) == '0')
                zeroes++;
            else
                ones++;
     
            dp[0][i] = ones * zeroes;
        }
     
        for (int s = 1; s < K; s++)
        {
            for (int i = 0; i < n; i++)
            {
     
                dp[s][i] = Integer.MAX_VALUE;
     
                ones = 0;
                zeroes = 0;
                for (int k = i; k >= 0; k--)
                {
                    if (str.charAt(k) == '0')
                        zeroes++;
                    else
                        ones++;
     
                    // If k = 0 then this arrangement is not possible
                    dp[s][i] = Math.min(dp[s][i],
                                +((k - 1 >= 0)
                                        ? ones * zeroes + dp[s - 1][k - 1]
                                        : Integer.MAX_VALUE));
                }
            }
        }
     
        // If no arrangement is possible then
        // our answer will remain INT_MAX so return -1
        return (dp[K - 1][n - 1] == Integer.MAX_VALUE) ? -1 : dp[K - 1][n - 1];
    }
     
    // Driver code
    public static void main (String[] args)
    {
     
        String S = "0101";
     
        // K buckets
        int K = 2;
     
        System.out.println(solve(S, K));
    }
}
 
// This code is contributed by ihritik


Python3




# Python3 implementation of the approach
import sys
 
# Function to find the minimum required
# sum using dynamic programming
def solve(Str, K):
    n = len(Str)
     
    # dp[i][j] = minimum val of accommodation
    # till j'th index of the string
    # using i+1 number of buckets.
    # Final ans will be in dp[n-1][K-1]
    # Initialise dp with all states as 0
    dp = [[0 for i in range(n)] for j in range(K)]
 
    # Corner cases
    if(n < K):
        return -1
    elif(n == K):
        return 0
 
    # Filling first row, if only 1 bucket then simple count
    # number of zeros and ones and do the multiplication
    zeroes = 0
    ones = 0
 
    for i in range(n):
        if(Str[i] == '0'):
            zeroes += 1
        else:
            ones += 1
        dp[0][i] = ones * zeroes
 
    for s in range(1, K):
        for i in range(n):
            dp[s][i] = sys.maxsize
            ones = 0
            zeroes = 0
 
            for k in range(i, -1, -1):
                if(Str[k] == '0'):
                    zeroes += 1
                else:
                    ones += 1
                 
                # If k = 0 then this arrangement
                # is not possible
                temp = 0
                if(k - 1 >= 0):
                    temp = ones * zeroes + dp[s - 1][k - 1]
                else:
                    temp = sys.maxsize
                dp[s][i] = min(dp[s][i], temp)
     
    # If no arrangement is possible then
    # our answer will remain INT_MAX so return -1
    if(dp[K - 1][n - 1] == sys.maxsize):
        return -1
    else:
        return dp[K - 1][n - 1]
       
# Driver code
S = "0101"
 
# K buckets
K = 2
print(solve(S, K))
 
# This code is contributed by avanitrachhadiya2155


C#




// C# implementation of the approach
using System;
 
class GFG
{
    // Function to find the minimum required
    // sum using dynamic programming
    static long solve(string str, int K)
    {
        int n = str.Length;
     
        // dp[i, j] = minimum val of accommodation
        // till j'th index of the string
        // using i+1 number of buckets.
        // Final ans will be in dp[n-1, K-1]
        long [, ] dp = new long[K, n];
     
     
        // Corner cases
        if (n < K)
            return -1;
        else if (n == K)
            return 0;
     
        // Filling first row, if only 1 bucket then simple count
        // number of zeros and ones and do the multiplication
        long zeroes = 0, ones = 0;
     
        for (int i = 0; i < n; i++)
        {
            if (str[i] == '0')
                zeroes++;
            else
                ones++;
     
            dp[0, i] = ones * zeroes;
        }
     
        for (int s = 1; s < K; s++)
        {
            for (int i = 0; i < n; i++)
            {
     
                dp[s, i] = Int32.MaxValue;
     
                ones = 0;
                zeroes = 0;
                for (int k = i; k >= 0; k--)
                {
                    if (str[k] == '0')
                        zeroes++;
                    else
                        ones++;
     
                    // If k = 0 then this arrangement is not possible
                    dp[s, i] = Math.Min(dp[s, i],
                                +((k - 1 >= 0)
                                        ? ones * zeroes + dp[s - 1, k - 1]
                                        : Int32.MaxValue));
                }
            }
        }
     
        // If no arrangement is possible then
        // our answer will remain INT_MAX so return -1
        return (dp[K - 1, n - 1] == Int32.MaxValue) ? -1 : dp[K - 1, n - 1];
    }
     
    // Driver code
    public static void Main (string[] args)
    {
     
        string S = "0101";
     
        // K buckets
        int K = 2;
     
        Console.WriteLine(solve(S, K));
     
    }
         
}
 
// This code is contributed by ihritik


Javascript




<script>
 
// JavaScript implementation of the approach
 
    // Function to find the minimum required
    // sum using dynamic programming
    function solve(str,K)
    {
        let n = str.length;
      
        // dp[i][j] = minimum val of accommodation
        // till j'th index of the string
        // using i+1 number of buckets.
        // Final ans will be in dp[n-1][K-1]
        let dp = new Array(K);
        for(let i=0;i<K;i++)
        {
            dp[i]=new Array(n);
            for(let j=0;j<n;j++)
            {
                dp[i][j]=0;
            }
        }
      
      
        // Corner cases
        if (n < K)
            return -1;
        else if (n == K)
            return 0;
      
        // Filling first row, if only 1 bucket then simple count
        // number of zeros and ones and do the multiplication
        let zeroes = 0, ones = 0;
      
        for (let i = 0; i < n; i++)
        {
            if (str[i] == '0')
                zeroes++;
            else
                ones++;
      
            dp[0][i] = ones * zeroes;
        }
      
        for (let s = 1; s < K; s++)
        {
            for (let i = 0; i < n; i++)
            {
      
                dp[s][i] = Number.MAX_VALUE;
      
                ones = 0;
                zeroes = 0;
                for (let k = i; k >= 0; k--)
                {
                    if (str[k] == '0')
                        zeroes++;
                    else
                        ones++;
      
                    // If k = 0 then this
                    // arrangement is not possible
                    dp[s][i] = Math.min(dp[s][i],
                                +((k - 1 >= 0)
                          ? ones * zeroes + dp[s - 1][k - 1]
                                        : Number.MAX_VALUE));
                }
            }
        }
      
        // If no arrangement is possible then
        // our answer will remain INT_MAX so return -1
        return (dp[K - 1][n - 1] == Number.MAX_VALUE) ?
        -1 : dp[K - 1][n - 1];
    }
     
    // Driver code
    let S = "0101";
    // K buckets
    let K = 2;
 
    document.write(solve(S, K));
 
 
// This code is contributed by patel2127
 
</script>


Output

2



Time Complexity: O(N3
Space Complexity: O(N2)

Efficient approach : Space optimization

In previous approach the current value dp[s][i] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.

Implementation steps:

  • Create a 1D vector dp of size n.
  • Set corner cases and base case by initializing the values of DP .
  • Create 2 values zeros and ones to store count.
  • Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
  • At last return the answer if exists in dp[n – 1] else return -1.

Implementation:

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum required
// sum using dynamic programming
int solve(string str, int K)
{
    int n = str.length();
    // dp[i][j] = minimum val of accommodation
    // till j'th index of the string
    // using i+1 number of buckets.
    // Final ans will be in dp[n-1][K-1]
    vector<long long> dp(n);
     
    // Corner cases
    if (n < K)
        return -1;
    else if (n == K)
        return 0;
     
    // Filling first row, if only 1 bucket then simple count
    // number of zeros and ones and do the multiplication
    long long zeroes = 0, ones = 0;
     
    for (int i = 0; i < n; i++) {
        if (str[i] == '0')
            zeroes++;
        else
            ones++;
     
        dp[i] = ones * zeroes;
    }
     
    for (int s = 1; s < K; s++) {
        for (int i = n-1; i >= 0; i--) {
     
            dp[i] = INT_MAX;
     
            ones = 0;
            zeroes = 0;
            for (int k = i; k >= 0; k--) {
                if (str[k] == '0')
                    zeroes++;
                else
                    ones++;
     
                // If k = 0 then this arrangement is not possible
                dp[i] = min(dp[i],
                            +((k - 1 >= 0)
                                    ? ones * zeroes + dp[k - 1]
                                    : INT_MAX));
            }
        }
    }
     
    // If no arrangement is possible then
    // our answer will remain INT_MAX so return -1
    return (dp[n - 1] == INT_MAX) ? -1 : dp[n - 1];
}
 
// Driver code
int main()
{
    string S = "0101";
     
    // K buckets
    int K = 2;
     
    cout << solve(S, K) << endl;
     
    return 0;
}


Java




import java.util.*;
 
public class Main {
    public static int solve(String str, int K) {
        int n = str.length();
        // dp[i][j] = minimum val of accommodation
        // till j'th index of the string
        // using i+1 number of buckets.
        // Final ans will be in dp[n-1][K-1]
        int[] dp = new int[n];
        Arrays.fill(dp, Integer.MAX_VALUE);
 
        // Corner cases
        if (n < K)
            return -1;
        else if (n == K)
            return 0;
 
        // Filling first row, if only 1 bucket then simple count
        // number of zeros and ones and do the multiplication
        long zeroes = 0, ones = 0;
        for (int i = 0; i < n; i++) {
            if (str.charAt(i) == '0')
                zeroes++;
            else
                ones++;
 
            dp[i] = (int) (ones * zeroes);
        }
 
        for (int s = 1; s < K; s++) {
            for (int i = n-1; i >= 0; i--) {
                ones = 0;
                zeroes = 0;
                for (int k = i; k >= 0; k--) {
                    if (str.charAt(k) == '0')
                        zeroes++;
                    else
                        ones++;
 
                    // If k = 0 then this arrangement is not possible
                    if (k - 1 >= 0)
                        dp[i] = Math.min(dp[i], (int) (ones * zeroes + dp[k - 1]));
                    else
                        dp[i] = Math.min(dp[i], (int) (ones * zeroes));
                }
            }
        }
 
        // If no arrangement is possible then
        // our answer will remain Integer.MAX_VALUE so return -1
        return (dp[n - 1] == Integer.MAX_VALUE) ? -1 : dp[n - 1];
    }
 
    // Driver code
    public static void main(String[] args) {
        String S = "0101";
        int K = 2;
        System.out.println(solve(S, K));
    }
}


Python3




# Python implementation of the approach
import sys
 
# Function to find the minimum required
# sum using dynamic programming
def solve(s, k):
    n = len(s)
    # dp[i] = minimum val of accommodation
    # till i'th index of the string
    # using k+1 number of buckets.
    # Final ans will be in dp[n-1]
    dp = [0] * n
 
    # Corner cases
    if n < k:
        return -1
    elif n == k:
        return 0
 
    # Filling first row, if only 1 bucket then simple count
    # number of zeros and ones and do the multiplication
    zeroes, ones = 0, 0
    for i in range(n):
        if s[i] == '0':
            zeroes += 1
        else:
            ones += 1
 
        dp[i] = ones * zeroes
 
    for s_ in range(1, k):
        for i in range(n-1, -1, -1):
            dp[i] = sys.maxsize
 
            ones, zeroes = 0, 0
            for k_ in range(i, -1, -1):
                if s[k_] == '0':
                    zeroes += 1
                else:
                    ones += 1
 
                # If k_ = 0 then this arrangement is not possible
                dp[i] = min(dp[i],
                            ((ones * zeroes + dp[k_ - 1])
                             if k_ - 1 >= 0 else sys.maxsize))
 
    # If no arrangement is possible then
    # our answer will remain sys.maxsize so return -1
    return -1 if dp[n - 1] == sys.maxsize else dp[n - 1]
 
# Driver code
if __name__ == '__main__':
    S = "0101"
 
    # K buckets
    K = 2
 
    print(solve(S, K))


C#




// C# implementation of the approach
using System;
using System.Collections.Generic;
 
public class GFG {
    // Function to find the minimum required
    // sum using dynamic programming
    static int Solve(string str, int K)
    {
        int n = str.Length;
        // dp[i] = minimum val of accommodation
        // till j'th index of the string
        // using i+1 number of buckets.
        // Final ans will be in dp[n-1][K-1]
        long[] dp = new long[n];
 
        // Corner cases
        if (n < K)
            return -1;
        else if (n == K)
            return 0;
 
        // Filling first row, if only 1 bucket then simple
        // count number of zeros and ones and do the
        // multiplication
        long zeroes = 0, ones = 0;
 
        for (int i = 0; i < n; i++) {
            if (str[i] == '0')
                zeroes++;
            else
                ones++;
 
            dp[i] = ones * zeroes;
        }
 
        for (int s = 1; s < K; s++) {
            for (int i = n - 1; i >= 0; i--) {
                dp[i] = int.MaxValue;
 
                ones = 0;
                zeroes = 0;
                for (int k = i; k >= 0; k--) {
                    if (str[k] == '0')
                        zeroes++;
                    else
                        ones++;
 
                    // If k = 0 then this arrangement is not
                    // possible
                    dp[i] = Math.Min(
                        dp[i],
                        ((k - 1 >= 0)
                             ? ones * zeroes + dp[k - 1]
                             : int.MaxValue));
                }
            }
        }
 
        // If no arrangement is possible then
        // our answer will remain int.MaxValue so return -1
        return (dp[n - 1] == int.MaxValue) ? -1
                                           : (int)dp[n - 1];
    }
 
    // Driver code
    static void Main(string[] args)
    {
        string S = "0101";
 
        // K buckets
        int K = 2;
 
        Console.WriteLine(Solve(S, K));
    }
}


Javascript




// Function to find the minimum required
// sum using dynamic programming
function solve(str, K) {
    let n = str.length;
    // dp[i][j] = minimum val of accommodation
    // till j'th index of the string
    // using i+1 number of buckets.
    // Final ans will be in dp[n-1][K-1]
    let dp = Array(n);
     
    // Corner cases
    if (n < K)
        return -1;
    else if (n == K)
        return 0;
     
    // Filling first row, if only 1 bucket then simple count
    // number of zeros and ones and do the multiplication
    let zeroes = 0, ones = 0;
     
    for (let i = 0; i < n; i++) {
        if (str[i] == '0')
            zeroes++;
        else
            ones++;
     
        dp[i] = ones * zeroes;
    }
     
    for (let s = 1; s < K; s++) {
        for (let i = n-1; i >= 0; i--) {
     
            dp[i] = Number.MAX_VALUE;
     
            ones = 0;
            zeroes = 0;
            for (let k = i; k >= 0; k--) {
                if (str[k] == '0')
                    zeroes++;
                else
                    ones++;
     
                // If k = 0 then this arrangement is not possible
                dp[i] = Math.min(dp[i],
                            +((k - 1 >= 0)
                                    ? ones * zeroes + dp[k - 1]
                                    : Number.MAX_VALUE));
            }
        }
    }
     
    // If no arrangement is possible then
    // our answer will remain INT_MAX so return -1
    return (dp[n - 1] == Number.MAX_VALUE) ? -1 : dp[n - 1];
}
 
// Driver code
let S = "0101";
// K buckets
let K = 2;
console.log(solve(S, K));


Output:

2

Time Complexity: O(n*K^2)

Auxiliary Space: O(N)
 



Last Updated : 13 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads