Split the array into N subarrays where each subarray has size 1 or sum at least K
Last Updated :
10 Feb, 2024
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++
#include <bits/stdc++.h>
using namespace std;
int isPartitionPossible( int arr[], int N, int K)
{
vector< int > pre(N + 1, 0);
for ( int i = 1; i <= N; i++)
pre[i] = arr[i - 1];
for ( int i = 1; i <= N; i++) {
pre[i] = pre[i] + pre[i - 1];
}
vector<vector< int > > dp(N + 1, vector< int >(N + 1, 0));
for ( int i = 0; i <= N; i++)
dp[i][i] = 1;
for ( int size = 1; size <= N; size++) {
for ( int i = 1; i <= N - size + 1; i++) {
int j = i + size - 1;
for ( int k = i; k < j; k++) {
if ((k - i == 0 or pre[k] - pre[i - 1] >= K)
and (j - k - 1 == 0
or pre[j] - pre[k] >= K))
dp[i][j]
= (dp[i][j]
| (dp[i][k] & dp[k + 1][j]));
}
}
}
return dp[1][N];
}
int main()
{
int N = 5, K = 6;
int arr[] = { 2, 3, 3, 2, 3 };
cout << isPartitionPossible(arr, N, K) << endl;
return 0;
}
|
Java
public class Main {
static boolean isPartitionPossible( int [] arr, int N,
int K)
{
int [] pre = new int [N + 1 ];
for ( int i = 1 ; i <= N; i++) {
pre[i] = arr[i - 1 ];
}
for ( int i = 1 ; i <= N; i++) {
pre[i] = pre[i] + pre[i - 1 ];
}
boolean [][] dp = new boolean [N + 1 ][N + 1 ];
for ( int i = 0 ; i <= N; i++) {
dp[i][i] = true ;
}
for ( int size = 1 ; size <= N; size++) {
for ( int i = 1 ; i <= N - size + 1 ; i++) {
int j = i + size - 1 ;
for ( int k = i; k < j; k++) {
if ((k - i == 0
|| pre[k] - pre[i - 1 ] >= K)
&& (j - k - 1 == 0
|| pre[j] - pre[k] >= K)) {
dp[i][j]
= dp[i][j]
|| (dp[i][k] && dp[k + 1 ][j]);
}
}
}
}
return dp[ 1 ][N];
}
public static void main(String[] args)
{
int N = 5 ;
int K = 6 ;
int [] arr = { 2 , 3 , 3 , 2 , 3 };
System.out.println(isPartitionPossible(arr, N, K));
}
}
|
Python3
def is_partition_possible(arr, N, K):
pre = [ 0 ] * (N + 1 )
for i in range ( 1 , N + 1 ):
pre[i] = arr[i - 1 ]
for i in range ( 1 , N + 1 ):
pre[i] = pre[i] + pre[i - 1 ]
dp = [[ 0 ] * (N + 1 ) for _ in range (N + 1 )]
for i in range (N + 1 ):
dp[i][i] = 1
for size in range ( 1 , N + 1 ):
for i in range ( 1 , N - size + 2 ):
j = i + size - 1
for k in range (i, j):
if ((k - i = = 0 or pre[k] - pre[i - 1 ] > = K) and
(j - k - 1 = = 0 or pre[j] - pre[k] > = K)):
dp[i][j] = dp[i][j] | (dp[i][k] & dp[k + 1 ][j])
return dp[ 1 ][N]
if __name__ = = "__main__" :
N = 5
K = 6
arr = [ 2 , 3 , 3 , 2 , 3 ]
print (is_partition_possible(arr, N, K))
|
C#
using System;
class GFG
{
static int IsPartitionPossible( int [] arr, int N, int K)
{
int [] pre = new int [N + 1];
for ( int i = 1; i <= N; i++)
pre[i] = arr[i - 1];
for ( int i = 1; i <= N; i++)
pre[i] = pre[i] + pre[i - 1];
int [,] dp = new int [N + 1, N + 1];
for ( int i = 0; i <= N; i++)
dp[i, i] = 1;
for ( int size = 1; size <= N; size++)
{
for ( int i = 1; i <= N - size + 1; i++)
{
int j = i + size - 1;
for ( int k = i; k < j; k++)
{
if ((k - i == 0 || pre[k] - pre[i - 1] >= K)
&& (j - k - 1 == 0 || pre[j] - pre[k] >= K))
{
dp[i, j] = (dp[i, j] | (dp[i, k] & dp[k + 1, j]));
}
}
}
}
return dp[1, N];
}
static void Main()
{
int N = 5, K = 6;
int [] arr = { 2, 3, 3, 2, 3 };
Console.WriteLine(IsPartitionPossible(arr, N, K));
}
}
|
Javascript
<script>
function isPartitionPossible(arr, N, K) {
let pre = new Array(N + 1).fill(0);
for (let i = 1; i <= N; i++) {
pre[i] = arr[i - 1];
}
for (let i = 1; i <= N; i++) {
pre[i] = pre[i] + pre[i - 1];
}
let dp = Array.from({ length: N + 1 }, () => Array(N + 1).fill( false ));
for (let i = 0; i <= N; i++) {
dp[i][i] = true ;
}
for (let size = 1; size <= N; size++) {
for (let i = 1; i <= N - size + 1; i++) {
let j = i + size - 1;
for (let k = i; k < j; k++) {
if ((k - i == 0 || pre[k] - pre[i - 1] >= K) && (j - k - 1 == 0 || pre[j] - pre[k] >= K)) {
dp[i][j] = dp[i][j] || (dp[i][k] && dp[k + 1][j]);
}
}
}
}
return dp[1][N];
}
let N = 5;
let K = 6;
let arr = [2, 3, 3, 2, 3];
console.log(isPartitionPossible(arr, N, K));
</script>
|
Time Complexity: O(N3), where N is the size of input array arr[].
Auxiliary Space: O(N2)
Share your thoughts in the comments
Please Login to comment...