Maximum sum of elements divisible by K from the given array
Last Updated :
26 Apr, 2023
Given an array of integers and a number K. The task is to find the maximum sum which is divisible by K from the given array.
Examples:
Input: arr[] = {3, 6, 5, 1, 8}, k = 3
Output: 18
Explanation: 18 is formed by the elements 3, 6, 1, 8.
Input: arr = { 43, 1, 17, 26, 15 } , k = 16
Output: 32
Explanation: 32 is formed by the elements 17, 15.
Naive Approach: Recursively check all the possible combinations to find the solution. The solution is of exponential time complexity and thus inefficient.
Efficient Approach: A dynamic programming approach by maintaining a 2-D array dp which stores the state of variable sum and i (where sum is the current sum and i is the ith index of integer array). By recurring over all elements, calculate the sum including the element at index i as well as excluding it and check if divisible by k. If so, store the maximum of them in dp[i][sum] and return.
Below code is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][1001];
int find_max( int i, int sum, vector< int >& v, int k)
{
if (i == v.size())
return 0;
if (dp[i][sum] != -1)
return dp[i][sum];
int ans = 0;
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
if ((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
ans = max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k,v, k));
return dp[i][sum] = ans;
}
int main()
{
vector< int > arr = { 43, 1, 17, 26, 15 };
int k = 16;
memset (dp, -1, sizeof (dp));
cout << find_max(0, 0, arr, k);
}
|
Java
class GFG{
static int [][]dp = new int [ 1001 ][ 1001 ];
static int find_max( int i, int sum, int []v, int k)
{
if (i == v.length)
return 0 ;
if (dp[i][sum] != - 1 )
return dp[i][sum];
int ans = 0 ;
if ((sum + find_max(i + 1 , sum, v, k)) % k == 0 )
ans = find_max(i + 1 , sum, v, k);
if ((sum + v[i] + find_max(i + 1 ,(sum + v[i]) % k,
v, k)) % k == 0 )
ans = Math.max(ans, v[i] + find_max(i + 1 ,
(sum + v[i]) % k, v, k));
return dp[i][sum] = ans;
}
public static void main(String[] args)
{
int []arr = { 43 , 1 , 17 , 26 , 15 };
int k = 16 ;
for ( int i = 0 ; i < 1001 ; i++)
for ( int j = 0 ; j < 1001 ; j++)
dp[i][j] = - 1 ;
System.out.print(find_max( 0 , 0 , arr, k));
}
}
|
Python 3
dp = [[ - 1 for i in range ( 1001 )] for j in range ( 1001 )]
def find_max(i, sum , v, k):
if (i = = len (v)):
return 0
if (dp[i][ sum ] ! = - 1 ):
return dp[i][ sum ]
ans = 0
if (( sum + find_max(i + 1 , sum , v, k)) % k = = 0 ):
ans = find_max(i + 1 , sum , v, k)
if (( sum + v[i] + find_max(i + 1 ,( sum + v[i]) % k, v, k)) % k = = 0 ):
ans = max (ans, v[i] + find_max(i + 1 ,( sum + v[i]) % k, v, k))
dp[i][ sum ] = ans
return dp[i][ sum ]
if __name__ = = '__main__' :
arr = [ 43 , 1 , 17 , 26 , 15 ]
k = 16
print (find_max( 0 , 0 , arr, k))
|
C#
using System;
class GFG{
static int [,]dp = new int [1001,1001];
static int find_max( int i, int sum, int []v, int k)
{
if (i == v.Length)
return 0;
if (dp[i,sum] != -1)
return dp[i,sum];
int ans = 0;
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
if ((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
ans = Math.Max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k, v, k));
return dp[i, sum] = ans;
}
public static void Main(String[] args)
{
int []arr = { 43, 1, 17, 26, 15 };
int k = 16;
for ( int i = 0; i < 1001; i++)
for ( int j = 0; j < 1001; j++)
dp[i,j] = -1;
Console.Write(find_max(0, 0, arr, k));
}
}
|
Javascript
<script>
let dp = new Array(1000 + 1);
function find_max(i, sum, v, k)
{
if (i == v.length)
return 0;
if (dp[i][sum] != -1)
return dp[i][sum];
let ans = 0;
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
if ((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
ans = Math.max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k,v, k));
return dp[i][sum] = ans;
}
let arr = [ 43, 1, 17, 26, 15 ];
let k = 16;
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
for ( var i = 0; i < dp.length; i++) {
for ( var j = 0; j < dp.length; j++) {
dp[i][j] = -1;
}
}
document.write(find_max(0, 0, arr, k));
</script>
|
Time Complexity: O(n*2^n)
Auxiliary Space: O(n*k)
Iterative implementation using top down dp:
We will be using the index and the modulus value of the sum as our states of dp. dp[i][j] would store the maximum sum of the array till ith index whose modulus is j.
C++
#include <bits/stdc++.h>
using namespace std;
int main()
{
int k=16;
vector< int >arr={ 43, 1, 17, 26, 15 } ;
int n=arr.size();
vector<vector< int >> dp(n+2, vector< int >(k, 0));
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j < k ; j++) {
dp[i][j] = dp[i - 1][j];
}
dp[i][arr[i - 1] % k] = max(dp[i][arr[i - 1] % k], arr[i - 1]);
for ( int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (dp[i - 1][j] != 0)
dp[i][m] = max(dp[i][m],arr[i - 1] + dp[i - 1][j]);
}
}
cout <<dp[n][0];
return 0;
}
|
Java
import java.util.*;
class GFG {
public static void main(String[] args)
{
int k = 16 ;
int [] arr = { 43 , 1 , 17 , 26 , 15 };
int n = arr.length;
int [][] dp = new int [n + 2 ][k];
for ( int i = 1 ; i <= n; i++) {
for ( int j = 0 ; j < k; j++) {
dp[i][j] = dp[i - 1 ][j];
}
dp[i][arr[i - 1 ] % k] = Math.max(
dp[i][arr[i - 1 ] % k], arr[i - 1 ]);
for ( int j = 0 ; j < k; j++) {
int m = (j + arr[i - 1 ]) % k;
if (dp[i - 1 ][j] != 0 )
dp[i][m] = Math.max(dp[i][m],
arr[i - 1 ]
+ dp[i - 1 ][j]);
}
}
System.out.print(dp[n][ 0 ]);
}
}
|
Python3
k = 16
arr = [ 43 , 1 , 17 , 26 , 15 ]
n = len (arr)
dp = [[ 0 for i in range (k)] for j in range (n + 2 )]
for i in range ( 1 , n + 1 ):
for j in range (k):
dp[i][j] = dp[i - 1 ][j]
dp[i][arr[i - 1 ] % k] = max (dp[i][arr[i - 1 ] % k], arr[i - 1 ])
for j in range (k):
m = (j + arr[i - 1 ]) % k
if dp[i - 1 ][j] ! = 0 :
dp[i][m] = max (dp[i][m],arr[i - 1 ] + dp[i - 1 ][j])
print (dp[n][ 0 ])
|
C#
using System;
class GFG {
static void Main() {
int k = 16;
int [] arr = { 43, 1, 17, 26, 15 };
int n = arr.Length;
int [,] dp = new int [n + 2, k];
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j < k ; j++) {
dp[i,j] = dp[i - 1,j];
}
dp[i,arr[i - 1] % k] = Math.Max(dp[i,arr[i - 1] % k], arr[i - 1]);
for ( int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (dp[i - 1,j] != 0)
dp[i,m] = Math.Max(dp[i,m],arr[i - 1] + dp[i - 1,j]);
}
}
Console.Write(dp[n,0]);
}
}
|
Javascript
<script>
let k = 16;
let arr = [ 43, 1, 17, 26, 15 ] ;
let n = arr.length;
let dp = new Array(n+2);
for (let i = 0; i < n+2; i++)
{
dp[i] = new Array(k);
for (let j = 0; j < k; j++)
{
dp[i][j] = 0;
}
}
for (let i = 1; i <= n; i++) {
for (let j = 0; j < k ; j++) {
dp[i][j] = dp[i - 1][j];
}
dp[i][arr[i - 1] % k] = Math.max(dp[i][arr[i - 1] % k], arr[i - 1]);
for (let j = 0; j < k; j++) {
let m = (j + arr[i - 1]) % k;
if (dp[i - 1][j] != 0)
dp[i][m] = Math.max(dp[i][m],arr[i - 1] + dp[i - 1][j]);
}
}
document.write(dp[n][0]);
</script>
|
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)
Efficient approach: Space optimization
In previous approach the dp[i][j] is depend upon the current and previous row of 2D matrix. So to optimize space we use two vectors curr and prev that keep track of current and previous row of DP.
Implementation Steps:
- Initialize two vectors curr and prev to keep track of only current and previous row of Dp with 0.
- Now iterative over subproblems and get the current computation.
- While iteration initialize curr vector.
- Now compute the current value by the help of prev vector and store that value in curr.
- After every iteration store values of curr vector in prev vector for further iteration.
- At last return the answer stored in curr[0].
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int findMax(vector< int > arr , int k , int n){
vector< int >prev(k+1, 0);
vector< int >curr(k+1, 0);
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j < k ; j++) {
curr[j] = prev[j];
}
curr[arr[i - 1] % k] = max(curr[arr[i - 1] % k], arr[i - 1]);
for ( int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (prev[j] != 0)
curr[m] = max(curr[m],arr[i - 1] + prev[j]);
}
prev = curr;
}
return curr[0];
}
int main()
{
int k=16;
vector< int >arr={ 43, 1, 17, 26, 15 } ;
int n=arr.size();
cout << findMax(arr, k , n);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int findMax(List<Integer> arr, int k, int n) {
int [] prev = new int [k+ 1 ];
int [] curr = new int [k+ 1 ];
for ( int i = 1 ; i <= n; i++) {
for ( int j = 0 ; j < k ; j++) {
curr[j] = prev[j];
}
curr[arr.get(i - 1 ) % k] = Math.max(curr[arr.get(i - 1 ) % k], arr.get(i - 1 ));
for ( int j = 0 ; j < k; j++) {
int m = (j + arr.get(i - 1 )) % k;
if (prev[j] != 0 )
curr[m] = Math.max(curr[m], arr.get(i - 1 ) + prev[j]);
}
prev = curr.clone();
}
return curr[ 0 ];
}
public static void main(String[] args) {
int k = 16 ;
List<Integer> arr = new ArrayList<>(Arrays.asList( 43 , 1 , 17 , 26 , 15 ));
int n = arr.size();
System.out.println(findMax(arr, k, n));
}
}
|
Python3
def findMax(arr, k, n):
prev = [ 0 ] * (k + 1 )
curr = [ 0 ] * (k + 1 )
for i in range ( 1 , n + 1 ):
for j in range (k):
curr[j] = prev[j]
curr[arr[i - 1 ] % k] = max (curr[arr[i - 1 ] % k], arr[i - 1 ])
for j in range (k):
m = (j + arr[i - 1 ]) % k
if prev[j] ! = 0 :
curr[m] = max (curr[m], arr[i - 1 ] + prev[j])
prev = curr.copy()
return curr[ 0 ]
k = 16
arr = [ 43 , 1 , 17 , 26 , 15 ]
n = len (arr)
print (findMax(arr, k, n))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int findMax(List< int > arr, int k, int n)
{
List< int > prev = new List< int >( new int [k + 1]);
List< int > curr = new List< int >( new int [k + 1]);
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j < k; j++) {
curr[j] = prev[j];
}
curr[arr[i - 1] % k] = Math.Max(
curr[arr[i - 1] % k], arr[i - 1]);
for ( int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (prev[j] != 0)
curr[m] = Math.Max(
curr[m], arr[i - 1] + prev[j]);
}
prev = new List< int >(curr);
}
return curr[0];
}
static void Main()
{
int k = 16;
List< int > arr = new List< int >{ 43, 1, 17, 26, 15 };
int n = arr.Count;
Console.WriteLine(findMax(arr, k, n));
}
}
|
Javascript
function findMax(arr, k, n) {
let prev = new Array(k + 1).fill(0);
let curr = new Array(k + 1).fill(0);
for (let i = 1; i <= n; i++) {
for (let j = 0; j < k; j++) {
curr[j] = prev[j];
}
curr[arr[i - 1] % k] = Math.max(curr[arr[i - 1] % k], arr[i - 1]);
for (let j = 0; j < k; j++) {
let m = (j + arr[i - 1]) % k;
if (prev[j] != 0) curr[m] = Math.max(curr[m], arr[i - 1] + prev[j]);
}
prev = [...curr];
}
return curr[0];
}
let k = 16;
let arr = [43, 1, 17, 26, 15];
let n = arr.length;
console.log(findMax(arr, k, n));
|
Time Complexity: O(N*K)
Auxiliary Space: O(K)
Share your thoughts in the comments
Please Login to comment...