当前位置: 面试刷题>> 数组划分 (经典算法题500道)


### 题目描述补充 **数组划分** 给定一个整数数组 `nums` 和一个整数 `k`,要求将数组 `nums` 划分为 `k` 个连续的子数组(每个子数组至少包含一个元素),使得这些子数组的最大和尽可能小。请返回这个最小的最大子数组和。 **示例 1**: ``` 输入: nums = [1, 2, 1, 2, 6, 7, 5, 1], k = 4 输出: 4 解释: 数组可以被划分为 [1, 2, 1], [2, 6], [7], [5, 1],每个子数组的和分别为 4, 8, 7, 6。 这些子数组的最大和是 8,但我们可以划分得更均匀些,得到 [1, 2], [1, 2], [6, 7], [5, 1], 此时最大和为 7。但是我们可以继续划分得到 [1], [2], [1], [2], [6], [7], [5], [1], 此时最大和为 6,但这不是最小的最大子数组和,因为我们可以得到 [1, 2, 1], [2, 6], [7], [5, 1], 此时最大和为 4,为所求。 ``` **示例 2**: ``` 输入: nums = [1, 2, 1, 4, 3, 5, 2, 6], k = 3 输出: 6 解释: 数组可以划分为 [1, 2, 1], [4, 3], [5, 2, 6],每个子数组的和分别为 4, 7, 13。 最大和为 13,但我们可以通过更均匀的划分得到 [1, 2], [1, 4], [3, 5, 2], [6], 此时最大和为 6,为所求。 ``` ### PHP 示例代码 ```php function splitArray($nums, $k) { $n = count($nums); $prefixSum = array_fill(0, $n + 1, 0); for ($i = 0; $i < $n; $i++) { $prefixSum[$i + 1] = $prefixSum[$i] + $nums[$i]; } $left = max($nums); // 最小可能的最大子数组和至少为数组中的最大元素 $right = $prefixSum[$n]; // 最大可能的最大子数组和是整个数组的和 while ($left < $right) { $mid = $left + floor(($right - $left) / 2); if (canPartition($prefixSum, $mid, $k)) { $right = $mid; } else { $left = $mid + 1; } } return $left; } function canPartition($prefixSum, $maxSum, $k) { $count = 1; // 已经分好的一组 $currentSum = 0; for ($i = 1; $i < count($prefixSum); $i++) { if ($prefixSum[$i] - $currentSum > $maxSum) { $count++; $currentSum = $prefixSum[$i]; if ($count > $k) { return false; } } else { $currentSum = $prefixSum[$i]; } } return true; } // 测试 $nums = [1, 2, 1, 2, 6, 7, 5, 1]; $k = 4; echo splitArray($nums, $k); // 输出 4 ``` ### Python 示例代码 ```python def splitArray(nums, k): n = len(nums) prefix_sum = [0] * (n + 1) for i in range(n): prefix_sum[i + 1] = prefix_sum[i] + nums[i] left = max(nums) right = prefix_sum[-1] while left < right: mid = (left + right) // 2 if can_partition(prefix_sum, mid, k): right = mid else: left = mid + 1 return left def can_partition(prefix_sum, max_sum, k): count = 1 current_sum = 0 for i in range(1, len(prefix_sum)): if prefix_sum[i] - current_sum > max_sum: count += 1 current_sum = prefix_sum[i] if count > k: return False else: current_sum = prefix_sum[i] return True # 测试 nums = [1, 2, 1, 2, 6, 7, 5, 1] k = 4 print(splitArray(nums, k)) # 输出 4 ``` ### JavaScript 示例代码 ```javascript function splitArray(nums, k) { const n = nums.length; const prefixSum = [0].concat(nums.reduce((acc, curr) => acc.concat(acc[acc.length - 1] + curr), [0])); let left = Math.max(...nums); let right = prefixSum[n]; while (left < right) { const mid = Math.floor((left + right) / 2); if (canPartition(prefixSum, mid, k)) { right = mid; } else { left = mid + 1; } } return left; } function canPartition(prefixSum, maxSum, k) { let count = 1; let currentSum = 0; for (let i = 1; i <= prefixSum.length - 1; i++) { if (prefixSum[i] - currentSum > maxSum) { count++; currentSum = prefixSum[i]; if (count > k) return false; } else { currentSum = prefixSum[i]; } } return true; } // 测试 const nums = [1, 2, 1, 2, 6, 7, 5, 1]; const k = 4; console.log(splitArray(nums, k)); // 输出 4 ``` 码小课网站中有更多相关内容分享给大家学习,涵盖各类算法和数据结构知识,帮助提升编程能力。
推荐面试题