Open In App

Split the array into N subarrays where each subarray has size 1 or sum at least K

Last Updated : 10 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N and integer K. Task for this problem is to check if given array can be split into N continuous subarrays by performing given operations. In one operation choose existing array which may be result of previous operation and split it into two subarrays with each of subarray follows at least one of the following properties:

  • The size of subarray is 1.
  • The sum of elements of that subarray is at least K.

Examples:

Input: arr[] = {2, 3, 3, 2, 3}, K = 6
Output: 1
Explanation:

  • In first operation partition {2, 3, 3, 2, 3} into {2, 3, 3, 2} + {3} each partitioned subarray satisfies required property. Subarrays are {{2, 3, 3, 2} + {3}}
  • In second operation partition {2, 3, 3, 2} into {2, 3, 3} + {2} each partitioned subarray satisfies required property. Subarrays are {{2, 3, 3} + {2} + {3}}
  • In third operation partition {2, 3, 3} into {2} + {3, 3} each partitioned subarray satisfies required property. Subarrays are {{2} + {3, 3} + {2} + {3}}
  • In fourth operation partition {3, 3} into {3} + {3} each partitioned subarray satisfies required property. Subarrays are {{2} + {3} + {3} + {2} + {3}}

so, it is possible to split given subarray into N subarrays.

Input: arr[] = {2, 1, 3}, K = 5
Output: 0
Explanation: Array arr[] cannot be partitioned into N = 3 subarrays by performing any operation

Approach: Implement the idea below to solve the problem:

Dynamic Programming can be used to solve this problem. The main concept of DP in the problem will be:

DP[i][j] will store whether it is possible to partition subarray from i to j (arr[i], arr[i + 1]……, arr[j])

Transition:

dp[i][j] = (dp[i][j] | dp[i][k] & dp[k + 1][j]) (splitting array for each k from i to j – 1)

Bitwise AND operation is used so when both arrays dp[i][k] and dp[k + 1][j] satisfies required property then only dp[i][j] will be 1. Also, to make sure while partitioning either one of above conditions is being satisfied by partitioned subarrays.

To check if partitioned subarray has sum at least K prefix sum array will be used.

Step-by-step algorithm:

  • Declare prefix array pre[N + 1] such that pre[i] stores the prefix sum till ith element.
  • Declare dp[N + 1][N + 1] and for every i from 0 to N update dp[i][i] as 1
  • To calculate answer for smaller subarrays, iterate from 1 to N as size and check for all values of i and j:
    • dp[i][j] = (dp[i][j] | dp[i][k] & dp[k + 1][j]) (splitting array for each k from i to j – 1)
  • Return dp[1][N] (which is answer whether array arr[] can be partitioned in N subarrays)

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to Check if array can be partitioned in N
// subarrays such that after each operation every partition
// have sum at least K or size 1
int isPartitionPossible(int arr[], int N, int K)
{
 
    // prefix sum array
    vector<int> pre(N + 1, 0);
 
    // filling prefix sum array
    for (int i = 1; i <= N; i++)
        pre[i] = arr[i - 1];
 
    // taking prefix sum
    for (int i = 1; i <= N; i++) {
        pre[i] = pre[i] + pre[i - 1];
    }
 
    // DP array initalized with 0
    vector<vector<int> > dp(N + 1, vector<int>(N + 1, 0));
 
    // Base Case
    for (int i = 0; i <= N; i++)
        dp[i][i] = 1;
 
    // iterating on each size of subarray
    for (int size = 1; size <= N; size++) {
 
        // iterating for start i
        for (int i = 1; i <= N - size + 1; i++) {
 
            // finding answer for array arr[i:j]
            int j = i + size - 1;
 
            // partitioning string at position k
            for (int k = i; k < j; k++) {
 
                // either one of the required property
                // should be true for paritioned subarrays
                if ((k - i == 0 or pre[k] - pre[i - 1] >= K)
                    and (j - k - 1 == 0
                         or pre[j] - pre[k] >= K))
 
                    // update dp table according to
                    // transitions
                    dp[i][j]
                        = (dp[i][j]
                           | (dp[i][k] & dp[k + 1][j]));
            }
        }
    }
 
    // returning final answer whether it is possible to
    // parition given array in N subarrays
    return dp[1][N];
}
 
// Driver Code
int main()
{
 
    // Input
    int N = 5, K = 6;
    int arr[] = { 2, 3, 3, 2, 3 };
 
    // Function Call
    cout << isPartitionPossible(arr, N, K) << endl;
 
    return 0;
}


Java




public class Main {
    // Function to check if partition is possible
    static boolean isPartitionPossible(int[] arr, int N,
                                       int K)
    {
        // Prefix sum array
        int[] pre = new int[N + 1];
 
        // Filling prefix sum array
        for (int i = 1; i <= N; i++) {
            pre[i] = arr[i - 1];
        }
 
        // Taking prefix sum
        for (int i = 1; i <= N; i++) {
            pre[i] = pre[i] + pre[i - 1];
        }
 
        // DP array initialized with 0
        boolean[][] dp = new boolean[N + 1][N + 1];
 
        // Base Case
        for (int i = 0; i <= N; i++) {
            dp[i][i] = true;
        }
 
        // Iterating on each size of subarray
        for (int size = 1; size <= N; size++) {
 
            // Iterating for start i
            for (int i = 1; i <= N - size + 1; i++) {
 
                // Finding answer for array arr[i:j]
                int j = i + size - 1;
 
                // Partitioning string at position k
                for (int k = i; k < j; k++) {
 
                    // Either one of the required property
                    // should be true for partitioned
                    // subarrays
                    if ((k - i == 0
                         || pre[k] - pre[i - 1] >= K)
                        && (j - k - 1 == 0
                            || pre[j] - pre[k] >= K)) {
 
                        // Update dp table according to
                        // transitions
                        dp[i][j]
                            = dp[i][j]
                              || (dp[i][k] && dp[k + 1][j]);
                    }
                }
            }
        }
 
        // Returning final answer whether it is possible to
        // partition the given array into N subarrays
        return dp[1][N];
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Input
        int N = 5;
        int K = 6;
        int[] arr = { 2, 3, 3, 2, 3 };
 
        // Function Call
        System.out.println(isPartitionPossible(arr, N, K));
    }
}


Python3




def is_partition_possible(arr, N, K):
    # prefix sum array
    pre = [0] * (N + 1)
 
    # filling prefix sum array
    for i in range(1, N + 1):
        pre[i] = arr[i - 1]
 
    # taking prefix sum
    for i in range(1, N + 1):
        pre[i] = pre[i] + pre[i - 1]
 
    # DP array initialized with 0
    dp = [[0] * (N + 1) for _ in range(N + 1)]
 
    # Base Case
    for i in range(N + 1):
        dp[i][i] = 1
 
    # iterating on each size of subarray
    for size in range(1, N + 1):
 
        # iterating for start i
        for i in range(1, N - size + 2):
 
            # finding answer for array arr[i:j]
            j = i + size - 1
 
            # partitioning string at position k
            for k in range(i, j):
 
                # either one of the required property
                # should be true for partitioned subarrays
                if ((k - i == 0 or pre[k] - pre[i - 1] >= K) and
                        (j - k - 1 == 0 or pre[j] - pre[k] >= K)):
 
                    # update dp table according to transitions
                    dp[i][j] = dp[i][j] | (dp[i][k] & dp[k + 1][j])
 
    # returning final answer whether it is possible to
    # partition given array into N subarrays
    return dp[1][N]
 
 
# Driver Code
if __name__ == "__main__":
    # Input
    N = 5
    K = 6
    arr = [2, 3, 3, 2, 3]
 
    # Function Call
    print(is_partition_possible(arr, N, K))


C#




using System;
 
class GFG
{
    // Function to check if array can be partitioned in N
    // subarrays such that after each operation every partition
    // has sum at least K or size 1
    static int IsPartitionPossible(int[] arr, int N, int K)
    {
        // Prefix sum array
        int[] pre = new int[N + 1];
 
        // Filling prefix sum array
        for (int i = 1; i <= N; i++)
            pre[i] = arr[i - 1];
 
        // Taking prefix sum
        for (int i = 1; i <= N; i++)
            pre[i] = pre[i] + pre[i - 1];
 
        // DP array initialized with 0
        int[,] dp = new int[N + 1, N + 1];
 
        // Base Case
        for (int i = 0; i <= N; i++)
            dp[i, i] = 1;
 
        // Iterating on each size of subarray
        for (int size = 1; size <= N; size++)
        {
            // Iterating for start i
            for (int i = 1; i <= N - size + 1; i++)
            {
                // Finding answer for array arr[i:j]
                int j = i + size - 1;
 
                // Partitioning string at position k
                for (int k = i; k < j; k++)
                {
                    // Either one of the required property
                    // should be true for partitioned subarrays
                    if ((k - i == 0 || pre[k] - pre[i - 1] >= K)
                        && (j - k - 1 == 0 || pre[j] - pre[k] >= K))
                    {
                        // Update dp table according to transitions
                        dp[i, j] = (dp[i, j] | (dp[i, k] & dp[k + 1, j]));
                    }
                }
            }
        }
 
        // Returning final answer whether it is possible to
        // partition the given array in N subarrays
        return dp[1, N];
    }
 
    // Driver Code
    static void Main()
    {
        // Input
        int N = 5, K = 6;
        int[] arr = { 2, 3, 3, 2, 3 };
 
        // Function Call
        Console.WriteLine(IsPartitionPossible(arr, N, K));
    }
}


Javascript




<script>
 
function isPartitionPossible(arr, N, K) {
    // Prefix sum array with an additional initial 0 for ease of calculation
    let pre = new Array(N + 1).fill(0);
 
    // Filling prefix sum array
    for (let i = 1; i <= N; i++) {
        pre[i] = arr[i - 1];
    }
 
    // Taking prefix sum
    for (let i = 1; i <= N; i++) {
        pre[i] = pre[i] + pre[i - 1];
    }
 
    // DP array initialized with false
    let dp = Array.from({ length: N + 1 }, () => Array(N + 1).fill(false));
 
    // Base Case
    for (let i = 0; i <= N; i++) {
        dp[i][i] = true;
    }
 
    // Iterating on each size of subarray
    for (let size = 1; size <= N; size++) {
        // Iterating for start i
        for (let i = 1; i <= N - size + 1; i++) {
            // Finding answer for array arr[i:j]
            let j = i + size - 1;
 
            // Partitioning string at position k
            for (let k = i; k < j; k++) {
                // Either one of the required property should be true for partitioned subarrays
                if ((k - i == 0 || pre[k] - pre[i - 1] >= K) && (j - k - 1 == 0 || pre[j] - pre[k] >= K)) {
                    // Update dp table according to transitions
                    dp[i][j] = dp[i][j] || (dp[i][k] && dp[k + 1][j]);
                }
            }
        }
    }
 
    // Returning final answer whether it is possible to partition the given array into subarrays
    return dp[1][N];
}
 
// Driver Code
let N = 5;
let K = 6;
let arr = [2, 3, 3, 2, 3];
 
// Function Call
console.log(isPartitionPossible(arr, N, K));
 
 
</script>


Output

1






Time Complexity: O(N3), where N is the size of input array arr[].
Auxiliary Space: O(N2)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads