Integer Break
Problem
Given an integer n, break it into the sum of k positive integers, where k >= 2, and maximize the product of those integers.
Return the maximum product you can get.
Examples
Example 1:
Input: n = 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.
Example 2:
Input: n = 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.
Solution
Method 1 – Dynamic Programming
Intuition
We want to break the integer n into at least two positive integers such that their product is maximized. For each number i, let dp[i] to be the max production value for breaking the number i. Since dp[i+j] can be i*j,
dp[i+j] = max(max(dp[i], i) * max(dp[j], j)), dp[i+j])
So, we can try every possible first split j (where 1 ≤ j < i) and take the maximum between splitting further (dp[i-j]) or not splitting (i-j). This way, we build up the solution from smaller numbers.
Approach
- Initialize a DP array
dpof sizen+1with all zeros. - Set
dp[1] = 1(base case). - For each
ifrom 2 ton, do:
- For each
jfrom 1 toi-1:- Compute the product of
jand the maximum ofdp[i-j]andi-j. - Update
dp[i]with the maximum value found.
- Compute the product of
- Return
dp[n]as the answer.
Code
C++
class Solution {
public:
int integerBreak(int n) {
std::vector<int> dp(n + 1, 0);
dp[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
dp[i] = std::max(dp[i], j * std::max(dp[i - j], i - j));
}
}
return dp[n];
}
};
Go
type Solution struct{}
func (Solution) IntegerBreak(n int) int {
dp := make([]int, n+1)
dp[1] = 1
for i := 2; i <= n; i++ {
for j := 1; j < i; j++ {
prod := j
if dp[i-j] > i-j {
prod *= dp[i-j]
} else {
prod *= i - j
}
if prod > dp[i] {
dp[i] = prod
}
}
}
return dp[n]
}
Java
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n + 1];
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
dp[i] = Math.max(dp[i], j * Math.max(dp[i - j], i - j));
}
}
return dp[n];
}
}
Kotlin
class Solution {
fun integerBreak(n: Int): Int {
val dp = IntArray(n + 1)
dp[1] = 1
for (i in 2..n) {
for (j in 1 until i) {
dp[i] = maxOf(dp[i], j * maxOf(dp[i - j], i - j))
}
}
return dp[n]
}
}
Python
class Solution:
def integerBreak(self, n: int) -> int:
dp: list[int] = [0] * (n + 1)
dp[1] = 1
for i in range(2, n + 1):
for j in range(1, i):
dp[i] = max(dp[i], j * max(dp[i - j], i - j))
return dp[n]
Rust
impl Solution {
pub fn integer_break(n: i32) -> i32 {
let n = n as usize;
let mut dp = vec![0; n + 1];
dp[1] = 1;
for i in 2..=n {
for j in 1..i {
dp[i] = dp[i].max(j * dp[i - j].max(i - j));
}
}
dp[n] as i32
}
}
Complexity
- ⏰ Time complexity:
O(n^2) - 🧺 Space complexity:
O(n)
Method 2 - Using Regularities
If we see the breaking result for some numbers, we can see repeated pattern like the following:
2 -> 1*1
3 -> 1*2
4 -> 2*2
5 -> 3*2
6 -> 3*3
7 -> 3*4
8 -> 3*3*2
9 -> 3*3*3
10 -> 3*3*4
11 -> 3*3*3*2
We only need to find how many 3's we can get when n> 4. If n%3==1, we do not want 1 to be one of the broken numbers, we want 4.
Code
C++
class Solution {
public:
int integerBreak(int n) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n == 4) return 4;
int result = 1;
if (n % 3 == 0) {
int m = n / 3;
for (int i = 0; i < m; ++i) result *= 3;
} else if (n % 3 == 2) {
int m = n / 3;
for (int i = 0; i < m; ++i) result *= 3;
result *= 2;
} else if (n % 3 == 1) {
int m = (n - 4) / 3;
for (int i = 0; i < m; ++i) result *= 3;
result *= 4;
}
return result;
}
};
Go
func integerBreak(n int) int {
if n == 2 {
return 1
}
if n == 3 {
return 2
}
if n == 4 {
return 4
}
result := 1
if n%3 == 0 {
m := n / 3
for i := 0; i < m; i++ {
result *= 3
}
} else if n%3 == 2 {
m := n / 3
for i := 0; i < m; i++ {
result *= 3
}
result *= 2
} else if n%3 == 1 {
m := (n - 4) / 3
for i := 0; i < m; i++ {
result *= 3
}
result *= 4
}
return result
}
Java
class Solution {
public int integerBreak(int n) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n == 4) return 4;
int result = 1;
if (n % 3 == 0) {
int m = n / 3;
result = (int) Math.pow(3, m);
} else if (n % 3 == 2) {
int m = n / 3;
result = (int) Math.pow(3, m) * 2;
} else if (n % 3 == 1) {
int m = (n - 4) / 3;
result = (int) Math.pow(3, m) * 4;
}
return result;
}
}
Kotlin
class Solution {
fun integerBreak(n: Int): Int {
if (n == 2) return 1
if (n == 3) return 2
if (n == 4) return 4
var result = 1
if (n % 3 == 0) {
val m = n / 3
repeat(m) { result *= 3 }
} else if (n % 3 == 2) {
val m = n / 3
repeat(m) { result *= 3 }
result *= 2
} else if (n % 3 == 1) {
val m = (n - 4) / 3
repeat(m) { result *= 3 }
result *= 4
}
return result
}
}
Python
class Solution:
def integerBreak(self, n: int) -> int:
if n == 2:
return 1
if n == 3:
return 2
if n == 4:
return 4
result = 1
if n % 3 == 0:
m = n // 3
result = 3 ** m
elif n % 3 == 2:
m = n // 3
result = (3 ** m) * 2
elif n % 3 == 1:
m = (n - 4) // 3
result = (3 ** m) * 4
return result
Rust
impl Solution {
pub fn integer_break(n: i32) -> i32 {
if n == 2 { return 1; }
if n == 3 { return 2; }
if n == 4 { return 4; }
let mut result = 1;
if n % 3 == 0 {
let m = n / 3;
for _ in 0..m {
result *= 3;
}
} else if n % 3 == 2 {
let m = n / 3;
for _ in 0..m {
result *= 3;
}
result *= 2;
} else if n % 3 == 1 {
let m = (n - 4) / 3;
for _ in 0..m {
result *= 3;
}
result *= 4;
}
result
}
}
Complexity
- ⏰ Time complexity:
O(1). All operations are constant time for reasonable n, as n ≤ 58 for Leetcode - 🧺 Space complexity:
O(1). no extra space used except a few variables