🧠
Brute Force (Pure Recursion / Nested Loops / etc.)
💡 Starting with brute force helps understand the problem deeply by exploring all possible splits, even though it’s inefficient.
Intuition
Try every possible way to split the array into m parts and calculate the largest sum for each split. The minimal among these is the answer.
Algorithm
- Define a recursive function that takes the start index and number of splits left.
- If only one split left, return sum of remaining elements.
- Otherwise, try all possible split points from start to end.
- For each split, recursively compute the largest sum for the remaining splits and take the minimal among all splits.
💡 The recursion explores all splits, which is conceptually simple but computationally expensive.
from typing import List
def splitArray(nums: List[int], m: int) -> int:
n = len(nums)
prefix = [0] * (n + 1)
for i in range(n):
prefix[i+1] = prefix[i] + nums[i]
def dfs(start: int, splits: int) -> int:
if splits == 1:
return prefix[n] - prefix[start]
min_largest = float('inf')
for i in range(start + 1, n - splits + 2):
left_sum = prefix[i] - prefix[start]
right_largest = dfs(i, splits - 1)
largest = max(left_sum, right_largest)
min_largest = min(min_largest, largest)
return min_largest
return dfs(0, m)
# Driver code
if __name__ == '__main__':
print(splitArray([7,2,5,10,8], 2)) # Expected output: 18
Line Notes
prefix = [0] * (n + 1)Create prefix sums for O(1) range sum queries
def dfs(start: int, splits: int) -> int:Recursive function to explore splits from start with splits left
if splits == 1:Base case: only one split means sum remaining elements
for i in range(start + 1, n - splits + 2):Try all possible split points ensuring enough elements remain
left_sum = prefix[i] - prefix[start]Sum of current subarray from start to i-1
right_largest = dfs(i, splits - 1)Recursively find largest sum for remaining splits
largest = max(left_sum, right_largest)Largest sum in this split configuration
min_largest = min(min_largest, largest)Keep track of minimal largest sum found
import java.util.*;
public class SplitArrayLargestSum {
public static int splitArray(int[] nums, int m) {
int n = nums.length;
int[] prefix = new int[n + 1];
for (int i = 0; i < n; i++) {
prefix[i + 1] = prefix[i] + nums[i];
}
return dfs(prefix, 0, m, n);
}
private static int dfs(int[] prefix, int start, int splits, int n) {
if (splits == 1) {
return prefix[n] - prefix[start];
}
int minLargest = Integer.MAX_VALUE;
for (int i = start + 1; i <= n - splits + 1; i++) {
int leftSum = prefix[i] - prefix[start];
int rightLargest = dfs(prefix, i, splits - 1, n);
int largest = Math.max(leftSum, rightLargest);
minLargest = Math.min(minLargest, largest);
}
return minLargest;
}
public static void main(String[] args) {
System.out.println(splitArray(new int[]{7,2,5,10,8}, 2)); // Expected: 18
}
}
Line Notes
int[] prefix = new int[n + 1];Prefix sums for quick range sum calculation
private static int dfs(int[] prefix, int start, int splits, int n)Recursive helper to explore splits
if (splits == 1)Base case: sum remaining elements
for (int i = start + 1; i <= n - splits + 1; i++)Try all valid split points
int leftSum = prefix[i] - prefix[start];Sum of current subarray
int rightLargest = dfs(prefix, i, splits - 1, n);Recursive call for remaining splits
int largest = Math.max(leftSum, rightLargest);Largest sum in this split
minLargest = Math.min(minLargest, largest);Track minimal largest sum
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int dfs(const vector<int>& prefix, int start, int splits, int n) {
if (splits == 1) {
return prefix[n] - prefix[start];
}
int minLargest = INT_MAX;
for (int i = start + 1; i <= n - splits + 1; i++) {
int leftSum = prefix[i] - prefix[start];
int rightLargest = dfs(prefix, i, splits - 1, n);
int largest = max(leftSum, rightLargest);
minLargest = min(minLargest, largest);
}
return minLargest;
}
int splitArray(vector<int>& nums, int m) {
int n = nums.size();
vector<int> prefix(n + 1, 0);
for (int i = 0; i < n; i++) {
prefix[i + 1] = prefix[i] + nums[i];
}
return dfs(prefix, 0, m, n);
}
int main() {
vector<int> nums = {7,2,5,10,8};
cout << splitArray(nums, 2) << endl; // Expected: 18
return 0;
}
Line Notes
vector<int> prefix(n + 1, 0);Prefix sums for O(1) subarray sums
int dfs(const vector<int>& prefix, int start, int splits, int n)Recursive function to try all splits
if (splits == 1)Base case: sum remaining elements
for (int i = start + 1; i <= n - splits + 1; i++)Try all valid split points
int leftSum = prefix[i] - prefix[start];Sum of current subarray
int rightLargest = dfs(prefix, i, splits - 1, n);Recursive call for remaining splits
int largest = max(leftSum, rightLargest);Largest sum in this split
minLargest = min(minLargest, largest);Track minimal largest sum
function splitArray(nums, m) {
const n = nums.length;
const prefix = new Array(n + 1).fill(0);
for (let i = 0; i < n; i++) {
prefix[i + 1] = prefix[i] + nums[i];
}
function dfs(start, splits) {
if (splits === 1) {
return prefix[n] - prefix[start];
}
let minLargest = Infinity;
for (let i = start + 1; i <= n - splits + 1; i++) {
const leftSum = prefix[i] - prefix[start];
const rightLargest = dfs(i, splits - 1);
const largest = Math.max(leftSum, rightLargest);
minLargest = Math.min(minLargest, largest);
}
return minLargest;
}
return dfs(0, m);
}
// Test
console.log(splitArray([7,2,5,10,8], 2)); // Expected: 18
Line Notes
const prefix = new Array(n + 1).fill(0);Prefix sums for quick subarray sums
function dfs(start, splits)Recursive function to explore splits
if (splits === 1)Base case: sum remaining elements
for (let i = start + 1; i <= n - splits + 1; i++)Try all valid split points
const leftSum = prefix[i] - prefix[start];Sum of current subarray
const rightLargest = dfs(i, splits - 1);Recursive call for remaining splits
const largest = Math.max(leftSum, rightLargest);Largest sum in this split
minLargest = Math.min(minLargest, largest);Track minimal largest sum
TimeO(n^m)
SpaceO(m) for recursion stack
For each of the m-1 splits, we try up to n positions, leading to exponential time.
💡 For n=10 and m=3, this means roughly 10^3=1000 operations, but for n=100, m=5 it explodes to 100^5=10 billion operations.
Interview Verdict: TLE
This approach is too slow for large inputs but helps understand the problem and forms the basis for optimization.