Split Array Largest Sum
Problem Description​
Given an integer array nums and an integer k, split nums into k non-empty subarrays such that the largest sum of any subarray is minimized.
Return the minimized largest sum of the split.
A subarray is a contiguous part of the array.
Examples​
Example 1:
Input: nums = [7,2,5,10,8], k = 2
Output: 18
Explanation: There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8], where the largest sum among the two subarrays is only 18.
Example 2:
Input: nums = [1,2,3,4,5], k = 2
Output: 9
Explanation: There are four ways to split nums into two subarrays.
The best way is to split it into [1,2,3] and [4,5], where the largest sum among the two subarrays is only 9.
Constraints​
1 <= nums.length <= 10000 <= nums[i] <= 1061 <= k <= min(50, nums.length)
Solution for Split Array Largest Sum​
Approach​
Brute Force​
- Generate all possible ways to split the array
numsintoksubarrays. - For each split, calculate the largest sum of the subarrays.
- Keep track of the minimum of these largest sums.
Complexity:
- Time Complexity:
O(C(n-1, k-1) * n), where C(n-1, k-1) is the number of ways to choose k-1 split points from n-1 positions, which is exponential. - Space Complexity: O(k), for storing split indices.
- Impractical for large inputs due to combinatorial explosion.
Corner Cases:
numswith a single element.kequal to the length ofnums, resulting in each element being its own subarray.kequal to 1, meaning the entire array is one subarray.
Optimized Approach (Binary Search + Greedy)​
- Use binary search to find the minimum possible largest sum
(low)and the maximum possible largest sum(high). lowis the maximum element innums(because each subarray must have at least one element).highis the sum of all elements innums(the entire array as one subarray).- Use binary search to narrow down the smallest valid
midvalue, wheremidrepresents the largest sum allowed for a subarray. - Use a greedy algorithm to check if it's possible to split
numsintoksubarrays with the largest subarray sum beingmid.
Implementation:
var splitArray = function(nums, k) {
const canSplit = (nums, k, mid) => {
let count = 1;
let currentSum = 0;
for (let num of nums) {
if (currentSum + num > mid) {
count++;
currentSum = num;
if (count > k) return false;
} else {
currentSum += num;
}
}
return true;
};
let left = Math.max(...nums);
let right = nums.reduce((a, b) => a + b, 0);
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (canSplit(nums, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
Complexity:
- Time Complexity:
O(n log(sum(nums) - max(nums))), wherenis the length ofnums. This is due to the binary search over the sum range and the linear scan to validate each mid value. - Space Complexity:
O(1), as we are not using extra space proportional to the input size.
Corner Cases:
numswith a single element: the result is that single element.kequal to the length ofnums: the result is the maximum element innums.kequal to 1: the result is the sum of all elements innums.- All elements in
numsare the same: the result should be one of those elements.
- Solution
Implementation​
Live Editor
function Solution(arr) { var splitArray = function(nums, k) { const canSplit = (nums, k, mid) => { let count = 1; let currentSum = 0; for (let num of nums) { if (currentSum + num > mid) { count++; currentSum = num; if (count > k) return false; } else { currentSum += num; } } return true; }; let left = Math.max(...nums); let right = nums.reduce((a, b) => a + b, 0); while (left < right) { let mid = Math.floor((left + right) / 2); if (canSplit(nums, k, mid)) { right = mid; } else { left = mid + 1; } } return left; }; const nums = [7, 2, 5, 10, 8]; const k = 2; const result = splitArray(nums, k); return ( <div> <p> <b>Input: </b> {JSON.stringify({ nums, k })} </p> <p> <b>Output:</b> {result} </p> </div> ); }
Result
Loading...
Complexity Analysis​
- Time Complexity:
- Space Complexity:
Code in Different Languages​
- JavaScript
- TypeScript
- Python
- Java
- C++
var splitArray = function(nums, k) {
const canSplit = (nums, k, mid) => {
let count = 1;
let currentSum = 0;
for (let num of nums) {
if (currentSum + num > mid) {
count++;
currentSum = num;
if (count > k) return false;
} else {
currentSum += num;
}
}
return true;
};
let left = Math.max(...nums);
let right = nums.reduce((a, b) => a + b, 0);
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (canSplit(nums, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
function splitArray(nums: number[], k: number): number {
const canSplit = (nums: number[], k: number, mid: number): boolean => {
let count = 1;
let currentSum = 0;
for (let num of nums) {
if (currentSum + num > mid) {
count++;
currentSum = num;
if (count > k) return false;
} else {
currentSum += num;
}
}
return true;
};
let left = Math.max(...nums);
let right = nums.reduce((a, b) => a + b, 0);
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (canSplit(nums, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
class Solution:
def splitArray(self, nums: List[int], k: int) -> int:
def canSplit(nums: List[int], k: int, mid: int) -> bool:
count = 1
current_sum = 0
for num in nums:
if current_sum + num > mid:
count += 1
current_sum = num
if count > k:
return False
else:
current_sum += num
return True
left, right = max(nums), sum(nums)
while left < right:
mid = (left + right) // 2
if canSplit(nums, k, mid):
right = mid
else:
left = mid + 1
return left
public class Solution {
public int splitArray(int[] nums, int k) {
int left = Arrays.stream(nums).max().getAsInt();
int right = Arrays.stream(nums).sum();
while (left < right) {
int mid = (left + right) / 2;
if (canSplit(nums, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
private boolean canSplit(int[] nums, int k, int mid) {
int count = 1;
int currentSum = 0;
for (int num : nums) {
if (currentSum + num > mid) {
count++;
currentSum = num;
if (count > k) {
return false;
}
} else {
currentSum += num;
}
}
return true;
}
}
class Solution {
public:
int splitArray(vector<int>& nums, int k) {
int left = *max_element(nums.begin(), nums.end());
int right = accumulate(nums.begin(), nums.end(), 0);
while (left < right) {
int mid = left + (right - left) / 2;
if (canSplit(nums, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
private:
bool canSplit(vector<int>& nums, int k, int mid) {
int count = 1;
int currentSum = 0;
for (int num : nums) {
if (currentSum + num > mid) {
count++;
currentSum = num;
if (count > k) {
return false;
}
} else {
currentSum += num;
}
}
return true;
}
};
References​
-
LeetCode Problem: Split Array Largest Sum
-
Solution Link: LeetCode Solution