# 410. Split Array Largest Sum

## 題目敘述

Given an array `nums` which consists of non-negative integers and an integer `m`, you can split the array into `m` non-empty continuous subarrays.

Write an algorithm to minimize the largest sum among these `m` subarrays.

Example 1:

``````Input: nums = [7,2,5,10,8], m = 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], m = 2
Output: 9
``````

Example 3:

``````Input: nums = [1,4,4], m = 3
Output: 4
``````

Constraints:

• `1 <= nums.length <= 1000`
• `0 <= nums[i] <= 10**6`
• `1 <= m <= min(50, nums.length)`

## 解法解析

### 解法範例

#### Go

``````func splitArray(nums []int, m int) int {
var minLargestSplitSum int
var left int
var right int

for _, num := range nums {
if num > left {
left = num
}
right += num
}

for left <= right {
maxSumAllowed := (left + right) / 2
if minSubarraysRequired(nums, maxSumAllowed) <= m {
right = maxSumAllowed - 1
minLargestSplitSum = maxSumAllowed
} else {
left = maxSumAllowed + 1
}
}

return minLargestSplitSum
}

func minSubarraysRequired(nums []int, maxSumAllowed int) int {
currentSum := 0
splitsRequired := 0

for _, element := range nums {
if currentSum+element <= maxSumAllowed {
currentSum += element
} else {
currentSum = element
splitsRequired++
}
}

splitsRequired++
return splitsRequired
}
``````

#### JavaScript

``````/**
* @param {number[]} nums
* @param {number} m
* @return {number}
*/
var splitArray = function (nums, m) {
const minSubarraysRequired = (maxSumAllowed) => {
let currentSum = 0,
splitsRequired = 0;
for (const element of nums) {
if (currentSum + element <= maxSumAllowed) {
currentSum += element;
} else {
currentSum = element;
splitsRequired++;
}
}
return splitsRequired + 1;
};

let minimumLargestSplitSum = 0,
left = Math.max(...nums),
right = nums.reduce((a, b) => a + b, 0);
while (left <= right) {
const maxSumAllowed = Math.floor((left + right) / 2);

if (minSubarraysRequired(maxSumAllowed) <= m) {
right = maxSumAllowed - 1;
minimumLargestSplitSum = maxSumAllowed;
} else {
left = maxSumAllowed + 1;
}
}

return minimumLargestSplitSum;
};
``````

#### Kotlin

``````class Solution {
fun splitArray(nums: IntArray, m: Int): Int {
var left = 0L
var right = 0L
for (num in nums) {
left = maxOf(left, num.toLong())
right += num
}
var minLargeestSplitSum = 0L

while (left <= right) {
val maxSumAllowed = left + (right - left) / 2
if (minSubArraysRequired(nums, maxSumAllowed) <= m) {
right = maxSumAllowed - 1
minLargeestSplitSum = maxSumAllowed
} else {
left = maxSumAllowed + 1
}
}

return minLargeestSplitSum.toInt()
}

private fun minSubArraysRequired(nums: IntArray, maxSumAllowed: Long): Int {
var currentSum = 0
var splitsRequired = 1

for (num in nums) {
if (currentSum + num <= maxSumAllowed) {
currentSum += num
} else {
splitsRequired++
currentSum = num
}
}
return splitsRequired
}
}
``````

#### PHP

``````
``````

#### Python

``````class Solution:
def splitArray(self, nums: List[int], m: int) -> int:

def min_subarrays_required(max_sum_allowed: int) -> int:
current_sum = 0
splits_required = 0

for element in nums:
# Add element only if the sum doesn't exceed max_sum_allowed
if current_sum + element <= max_sum_allowed:
current_sum += element
else:
# If the element addition makes sum more than max_sum_allowed
# Increment the splits required and reset sum
current_sum = element
splits_required += 1

# Return the number of subarrays, which is the number of splits + 1
return splits_required + 1

# Define the left and right boundary of binary search
left, right = max(nums), sum(nums)
while left <= right:
# Find the mid value
max_sum_allowed = (left + right) // 2

# Find the minimum splits. If splits_required is less than
# or equal to m move towards left i.e., smaller values
if min_subarrays_required(max_sum_allowed) <= m:
right = max_sum_allowed - 1
minimum_largest_split_sum = max_sum_allowed
else:
# Move towards right if splits_required is more than m
left = max_sum_allowed + 1

return minimum_largest_split_sum
``````

#### Rust

``````
``````

#### Swift

``````class Solution {
func splitArray(_ nums: [Int], _ m: Int) -> Int {
var minLargetSplitSum = 0
var left = nums.max()!
var right = nums.reduce(0, +)
while left <= right {
let maxSumAllowed = (left + right) / 2

if minSubarraysRequired(nums, maxSumAllowed) <= m{
right = maxSumAllowed - 1
minLargetSplitSum = maxSumAllowed
} else {
left = maxSumAllowed + 1
}
}

return minLargetSplitSum
}

func minSubarraysRequired(_ nums: [Int], _ max_sum_allowed: Int) -> Int {
var currentSum = 0
var splitsRequired = 0

for num in nums {
if currentSum + num <= max_sum_allowed {
currentSum += num
} else {
currentSum = num
splitsRequired += 1
}
}

return splitsRequired + 1
}
}
``````