# Maximize the numbers of splits in an Array having sum divisible by 3

• Last Updated : 19 Jul, 2021

Given an integer array arr of size N. The task is to find the maximum number of splits such that each split has sum divisible by 3. It is not necessary that all splits are divisible by 3, the task is to just maximize the number of splits which are divisible by 3.
Examples:

Input: arr [] = [2, 36, 1, 9, 2, 0, 1, 8, 1]
Output:
Explanation
The array can be splited into 4 parts:
[2, 36, 1] Sum = 39
 Sum = 9
[2, 0, 1] Sum = 3
[8, 1] Sum = 9
All splits are divisible by 3 and there cannot be more than 4 splits which are divisible by 3.
Input: arr [] = [40, 40, 40, 5]
Output:
Explanation:
Array can be splits into only two parts
[40, 40] Sum = 80.
[40, 5] Sum = 45.
The sum of the second split is divisible by 3 hence only one split is divisible by 3 so the output is 1.

Approach
One observation that can be made easily is that it is easier to work with the array if we take modulo of every element by 3. Because it would not have any effect in the splits. Now the problem can be solved using Dynamic Programming

1. Let dp[i] signifies maximum number of splits at position i

2. Then calculate the prefix sums modulo 3.
3. So if a segment has sum divisible by 3 and its left and right prefix sum will also be same.
4. Another thing to notice is that prefix sums modulo 3 can be either 0, 1 or 2 . So if the current prefix sum modulo 3 is 1. Choose the left pointer as the right most index which has prefix sum 1. Or ignore the segment and move on.

dp[i] = max( dp[right most index from 0 to i with prefix sum same as i] + 1, dp[i-1])
dp[i-1] means we are not considering i as right pointer of some segment .
dp[right most index from 0 to i with prefix sum same as i]+1 means i is a right pointer of the segment and total number of splits will be the total number of splits at the left pointer of the segment + 1 (for this segment) .

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach` `#include` `using` `namespace` `std;`   `int` `calculate_maximum_splits(``int` `arr[], ``int` `N)` `{` `    `  `    ``// Prefix array storing right most` `    ``// index with prefix sums 0, 1, 2` `    ``int` `pre[] = { 0, -1, -1 };     `   `    ``// dp array` `    ``int` `dp[N];` `    ``memset``(dp, 0, ``sizeof``(dp));` `    `  `    ``// Current prefix sum` `    ``int` `C = 0;`   `    ``for``(``int` `i = 0; i < N; i++)` `    ``{` `       ``C = C + arr[i];` `       `  `       ``// Calculating the prefix sum modulo 3` `       ``C = C % 3;` `       `  `       ``// We dont have a left pointer` `       ``// with prefix sum C` `       ``if` `(pre[C] == -1)` `       ``{` `           ``dp[i] = dp[i - 1];` `           `  `           ``// We cannot consider i as` `           ``// a right pointer of any segment` `       ``}` `       ``else` `       ``{` `           `  `           ``// We have a left pointer ` `           ``// pre[C] with prefix sum C` `           ``dp[i] = max(dp[i - 1], dp[pre[C]] + 1);` `       ``}` `       `  `       ``// i is the rightmost index of ` `       ``// prefix sum C` `       ``pre[C] = i;` `    ``}` `    ``return` `dp[N - 1];` `}`   `// Driver code` `int` `main()` `{` `    ``int` `arr[] = { 2, 36, 1, 9, 2, 0, 1, 8, 1 };` `    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` `    `  `    ``cout << (calculate_maximum_splits(arr, N));` `}`   `// This code is contributed by chitranayal`

## Java

 `// Java implementation of the above approach` `import` `java.util.*;`   `class` `GFG{`   `static` `int` `calculate_maximum_splits(``int` `arr[],` `                                    ``int` `N)` `{` `    `  `    ``// Prefix array storing right most` `    ``// index with prefix sums 0, 1, 2` `    ``int` `pre[] = { ``0``, -``1``, -``1` `};     `   `    ``// dp array` `    ``int``[] dp = ``new` `int``[N];` `    ``Arrays.fill(dp, ``0``);` `    `  `    ``// Current prefix sum` `    ``int` `C = ``0``;`   `    ``for``(``int` `i = ``0``; i < N; i++)` `    ``{` `        ``C = C + arr[i];` `            `  `        ``// Calculating the prefix sum modulo 3` `        ``C = C % ``3``;` `            `  `        ``// We dont have a left pointer` `        ``// with prefix sum C` `        ``if` `(pre[C] == -``1``)` `        ``{` `            ``if``(``1` `<= i)` `            ``dp[i] = dp[i - ``1``];` `                `  `            ``// We cannot consider i as` `            ``// a right pointer of any segment` `        ``}` `        ``else` `        ``{` `            `  `            ``// We have a left pointer ` `            ``// pre[C] with prefix sum C` `            ``dp[i] = Math.max(dp[i - ``1``], ` `                             ``dp[pre[C]] + ``1``);` `        ``}` `        `  `        ``// i is the rightmost index of ` `        ``// prefix sum C` `        ``pre[C] = i;` `    ``}` `    ``return` `dp[N - ``1``];` `}`   `// Driver code` `public` `static` `void` `main(String[] args)` `{` `    ``int` `arr[] = { ``2``, ``36``, ``1``, ``9``, ``2``, ``0``, ``1``, ``8``, ``1` `};` `    ``int` `N = arr.length;`   `    ``System.out.println(calculate_maximum_splits(arr, N));` `}` `}`   `// This code is contributed by offbeat`

## Python3

 `# Python3 program for above approach` `def` `calculate_maximum_splits(arr, N):`   `    ``# prefix array storing right most` `    ``# index with prefix sums 0, 1, 2` `    ``pre ``=``[``0``, ``-``1``, ``-``1``]         `   `    ``# dp array` `    ``dp ``=``[``0` `for` `i ``in` `range``(N)]` `    ``# current prefix sum` `    ``C ``=` `0`   `    ``for` `i ``in` `range``(N):`   `        ``C ``=` `C ``+` `arr[i]`   `        ``# Calculating the prefix sum modulo 3` `        ``C ``=` `C ``%` `3`   `        ``# We dont have a left pointer` `        ``# with prefix sum C` `        ``if` `pre[C]``=``=``-``1``:`   `            ``dp[i]``=` `dp[i``-``1``] ` `            ``# We cannot consider i as` `            ``# a right pointer of any segment` `        ``else``:` `            ``# We have a left pointer ` `            ``# pre[C] with prefix sum C` `            ``dp[i]``=` `max``(dp[i``-``1``], dp[pre[C]]``+``1``)`   `        ``# i is the rightmost index of ` `        ``# prefix sum C` `        ``pre[C]``=` `i `   `    ``return` `dp[N``-``1``]` `# Driver code` `arr ``=` `[``2``, ``36``, ``1``, ``9``, ``2``, ``0``, ``1``, ``8``, ``1``] ` `N ``=` `len``(arr)` `print``(calculate_maximum_splits(arr, N))     `

## C#

 `// C# implementation of the above approach` `using` `System;`   `class` `GFG{`   `static` `int` `calculate_maximum_splits(``int` `[]arr,` `                                    ``int` `N)` `{` `    `  `    ``// Prefix array storing right most` `    ``// index with prefix sums 0, 1, 2` `    ``int` `[]pre = { 0, -1, -1 };     `   `    ``// dp array` `    ``int``[] dp = ``new` `int``[N];` `    ``for``(``int` `i = 0; i < N; i++)` `    ``{` `        ``dp[i] = 0;` `    ``}` `    `  `    ``// Current prefix sum` `    ``int` `C = 0;`   `    ``for``(``int` `i = 0; i < N; i++)` `    ``{` `        ``C = C + arr[i];` `            `  `        ``// Calculating the prefix sum modulo 3` `        ``C = C % 3;` `            `  `        ``// We dont have a left pointer` `        ``// with prefix sum C` `        ``if` `(pre[C] == -1)` `        ``{` `            ``if``(1 <= i)` `            ``dp[i] = dp[i - 1];` `                `  `            ``// We cannot consider i as` `            ``// a right pointer of any segment` `        ``}` `        ``else` `        ``{` `            `  `            ``// We have a left pointer ` `            ``// pre[C] with prefix sum C` `            ``dp[i] = Math.Max(dp[i - 1], ` `                             ``dp[pre[C]] + 1);` `        ``}` `        `  `        ``// i is the rightmost index of ` `        ``// prefix sum C` `        ``pre[C] = i;` `    ``}` `    ``return` `dp[N - 1];` `}`   `// Driver code` `public` `static` `void` `Main(``string``[] args)` `{` `    ``int` `[]arr = { 2, 36, 1, 9, 2, 0, 1, 8, 1 };` `    ``int` `N = arr.Length;`   `    ``Console.Write(calculate_maximum_splits(arr, N));` `}` `}`   `// This code is contributed by rutvik_56`

## Javascript

 ``

Output:

`4`

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

My Personal Notes arrow_drop_up
Recommended Articles
Page :