Recursively break a number in 3 parts to get maximum sum
Given a number n, we can divide it in only three parts n/2, n/3 and n/4 (we will consider only integer part). The task is to find the maximum sum we can make by dividing number in three parts recursively and summing up them together.
Examples:
Input : n = 12
Output : 13
// We break n = 12 in three parts {12/2, 12/3, 12/4}
// = {6, 4, 3}, now current sum is = (6 + 4 + 3) = 13
// again we break 6 = {6/2, 6/3, 6/4} = {3, 2, 1} = 3 +
// 2 + 1 = 6 and further breaking 3, 2 and 1 we get maximum
// summation as 1, so breaking 6 in three parts produces
// maximum sum 6 only similarly breaking 4 in three
// parts we can get maximum sum 4 and same for 3 also.
// Thus maximum sum by breaking number in parts is=13
Input : n = 24
Output : 27
// We break n = 24 in three parts {24/2, 24/3, 24/4}
// = {12, 8, 6}, now current sum is = (12 + 8 + 6) = 26
// As seen in example, recursively breaking 12 would
// produce value 13. So our maximum sum is 13 + 8 + 6 = 27.
// Note that recursively breaking 8 and 6 doesn't produce
// more values, that is why they are not broken further.
Input : n = 23
Output : 23
// we break n = 23 in three parts {23/2, 23/3, 23/4} =
// {10, 7, 5}, now current sum is = (10 + 7 + 5) = 22.
// Since after further breaking we can not get maximum
// sum hence number is itself maximum i.e; answer is 23
A simple solution for this problem is to do it recursively. In each call we have to check only max((max(n/2) + max(n/3) + max(n/4)), n) and return it. Because either we can get maximum sum by breaking number in parts or number is itself maximum. Below is the implementation of recursive algorithm.
C++
#include<bits/stdc++.h>
using namespace std;
int breakSum( int n)
{
if (n==0 || n == 1)
return n;
return max((breakSum(n/2) + breakSum(n/3) +
breakSum(n/4)), n);
}
int main()
{
int n = 120;
cout << breakSum(n);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int breakSum( int n)
{
if (n== 0 || n == 1 )
return n;
return Math.max((breakSum(n/ 2 ) + breakSum(n/ 3 ) +
breakSum(n/ 4 )), n);
}
public static void main (String[] args) {
int n = 12 ;
System.out.println(breakSum(n));
}
}
|
Python3
def breakSum(n) :
if (n = = 0 or n = = 1 ) :
return n
return max ((breakSum(n / / 2 ) +
breakSum(n / / 3 ) +
breakSum(n / / 4 )), n)
if __name__ = = "__main__" :
n = 12
print (breakSum(n))
|
C#
using System;
class GFG {
static int breakSum( int n)
{
if (n==0 || n == 1)
return n;
return Math.Max((breakSum(n/2)
+ breakSum(n/3)
+ breakSum(n/4)), n);
}
public static void Main ()
{
int n = 12;
Console.WriteLine(breakSum(n));
}
}
|
PHP
<?php
function breakSum( $n )
{
if ( $n == 0 || $n == 1)
return $n ;
return max((breakSum( intval ( $n / 2)) +
breakSum( intval ( $n / 3)) +
breakSum( intval ( $n / 4))), $n );
}
$n = 12;
echo breakSum( $n );
?>
|
Javascript
<script>
function breakSum(n)
{
if (n==0 || n == 1)
return n;
return Math.max((breakSum(Math.floor(n/2)) +
breakSum(Math.floor(n/3)) +
breakSum(Math.floor(n/4))), n);
}
let n = 12;
document.write(breakSum(n));
</script>
|
Memoization of Recursive Solution
In the above solution, we see that there are many overlapping functions calls become so to reduce that we memoize the above recursive solution so it’s time complexity reduce exponentially to linear.
C++
#include<bits/stdc++.h>
using namespace std;
int breakSum( int n, vector< int >&dp)
{
if (n == 0 || n == 1) {
return n;
}
if (dp[n] != -1) {
return dp[n];
}
return dp[n] = max((breakSum(n / 2, dp) + breakSum(n / 3, dp) + breakSum(n / 4, dp)), n);
}
int main() {
int n = 24;
vector< int >dp(n + 1, -1);
cout << breakSum(n, dp);
return 0;
}
|
Java
class Main {
public static int breakSum( int n, int [] dp)
{
if (n == 0 || n == 1 )
return n;
if (dp[n] != - 1 ) {
return dp[n];
}
return dp[n] = Math.max((breakSum(n / 2 , dp) + breakSum(n / 3 , dp) + breakSum(n / 4 , dp)), n);
}
public static void main (String[] args) {
int n = 24 ;
int [] dp = new int [n+ 1 ];
for ( int i = 0 ; i <= n; i++) dp[i] = - 1 ;
System.out.println(breakSum(n, dp));
}
}
|
Python3
def breakSum(n, dp):
if n = = 0 or n = = 1 :
return n
if dp[n] ! = - 1 :
return dp[n]
dp[n] = max ((breakSum(n / / 2 , dp) + breakSum(n / / 3 , dp) + breakSum(n / / 4 , dp)), n)
return dp[n]
if __name__ = = "__main__" :
n = 24
dp = [ - 1 for i in range (n + 1 )]
print (breakSum(n, dp))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int breakSum( int n, List< int > dp)
{
if (n == 0 || n == 1) {
return n;
}
if (dp[n] != -1) {
return dp[n];
}
return dp[n] = Math.Max((breakSum(n / 2, dp) +
breakSum(n / 3, dp) +
breakSum(n / 4, dp)), n);
}
static public void Main()
{
int n = 24;
List< int >dp = new List< int >();
for ( int i = 0; i < n + 1; i++)
dp.Add(-1);
Console.Write(breakSum(n, dp));
}
}
|
Javascript
function breakSum(n, dp)
{
if (n == 0 || n == 1) {
return n;
}
if (dp[n] != -1) {
return dp[n];
}
return dp[n] = Math.max((breakSum(parseInt(n / 2), dp) +
breakSum(parseInt(n / 3), dp) + breakSum(parseInt(n / 4), dp)), n);
}
let n = 24;
let dp= new Array(n + 1).fill(-1);
console.log(breakSum(n, dp));
|
Time Complexity: O(n)
Auxiliary Space: O(n) (as we are creating dp array of size n+1)
An efficient solution for this problem is to use Dynamic programming because while breaking the number in parts recursively we have to perform some overlapping problems. For example part of n = 30 will be {15,10,7} and part of 15 will be {7,5,3} so we have to repeat the process for 7 two times for further breaking. To avoid this overlapping problem we are using Dynamic programming. We store values in an array and if for any number in recursive calls we have already solution for that number currently so we directly extract it from array.
C++
#include<bits/stdc++.h>
#define MAX 1000000
using namespace std;
int breakSum( int n)
{
int dp[n+1];
dp[0] = 0, dp[1] = 1;
for ( int i=2; i<=n; i++)
dp[i] = max(dp[i/2] + dp[i/3] + dp[i/4], i);
return dp[n];
}
int main()
{
int n = 24;
cout << breakSum(n);
return 0;
}
|
Java
import java.io.*;
class GFG {
final int MAX = 1000000 ;
static int breakSum( int n)
{
int dp[] = new int [n+ 1 ];
dp[ 0 ] = 0 ; dp[ 1 ] = 1 ;
for ( int i= 2 ; i<=n; i++)
dp[i] = Math.max(dp[i/ 2 ] + dp[i/ 3 ] + dp[i/ 4 ], i);
return dp[n];
}
public static void main (String[] args) {
int n = 24 ;
System.out.println(breakSum(n));
}
}
|
Python3
MAX = 1000000
def breakSum(n):
dp = [ 0 ] * (n + 1 )
dp[ 0 ] = 0
dp[ 1 ] = 1
for i in range ( 2 , n + 1 ):
dp[i] = max (dp[ int (i / 2 )] + dp[ int (i / 3 )] + dp[ int (i / 4 )], i);
return dp[n]
n = 24
print (breakSum(n))
|
C#
using System;
class GFG {
static int breakSum( int n)
{
int []dp = new int [n+1];
dp[0] = 0; dp[1] = 1;
for ( int i = 2; i <= n; i++)
dp[i] = Math.Max(dp[i/2] +
dp[i/3] + dp[i/4], i);
return dp[n];
}
public static void Main ()
{
int n = 24;
Console.WriteLine(breakSum(n));
}
}
|
PHP
<?php
function breakSum( $n )
{
$dp = array_fill (0, $n + 1, 0);
$dp [0] = 0;
$dp [1] = 1;
for ( $i = 2; $i <= $n ; $i ++)
$dp [ $i ] = max( $dp [(int)( $i / 2)] +
$dp [(int)( $i / 3)] +
$dp [(int)( $i / 4)], $i );
return $dp [ $n ];
}
$n = 24;
echo breakSum( $n );
?>
|
Javascript
<script>
let MAX = 1000000;
function breakSum(n)
{
let dp= new Array(n+1);
for (let i=0;i<dp;i++)
{
dp[i]=0;
}
dp[0] = 0; dp[1] = 1;
for (let i=2; i<=n; i++)
dp[i] = Math.max(dp[(Math.floor(i/2))] +
dp[(Math.floor(i/3))] + dp[(Math.floor(i/4))], i);
return dp[n];
}
let n = 24;
document.write(breakSum(n));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Last Updated :
24 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...