[LeetCode] 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] <= 106
1 <= m <= min(50, nums.length)
分割数组的最大值。
给定一个非负整数数组 nums 和一个整数 m ,你需要将这个数组分成 m 个非空的连续子数组。
设计一个算法使得这 m 个子数组各自和的最大值最小。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/split-array-largest-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题我给出一个比较好理解的二分法。这道题也有动态规划的做法,以后有机会再补充。
我第一次做这道题的时候觉得题意有点绕,这里重新解释一下。这道题是要你将数组分割成 M 个部分,分割之后每个子数组都是有一个各自的数组合的,所以一共会得到 M 个数组合。你要做的是找到一个分割方式使得这 M 个数组合中的最大值尽可能小。
这道题的二分法找的就是到底这个子数组的合是多少才比较合适,属于在答案上二分的题。既然是查找就得有范围,这里查找的下界是数组里的最大值 max,因为题目中给的 M 是有可能等于 input 数组长度的,也就是每个元素组成一个子数组;查找的上界是整个数组的前缀和,因为题目中给的 M 是有可能等于 1 的,也就是不分割这个数组。我这里用了一个 helper 函数去判断 mid 是否合适,其他的参见代码注释。注意二分写法的不同,14,15 行和 20,21 行。
时间O(nlogn)
空间O(1)
Java实现
1 class Solution { 2 public int splitArray(int[] nums, int m) { 3 int max = Arrays.stream(nums).max().getAsInt(); 4 long sum = Arrays.stream(nums).sum(); 5 6 // corner case 7 if (m == 1) { 8 return (int) sum; 9 } 10 11 // normal case 12 long left = max; 13 long right = sum; 14 // while (left < right) { 15 while (left <= right) { 16 // 我们二分得到一个mid值,假设按照这个值来分割,看看能否分割成m份 17 long mid = left + (right - left) / 2; 18 // 如果可以分割成m份,那我们试着把mid再变小 19 if (helper(nums, m, mid)) { 20 // right = mid; 21 right = mid - 1; 22 } 23 // 不能分割成m份,子数组的和一定要变大 24 else { 25 left = mid + 1; 26 } 27 } 28 return (int) left; 29 } 30 31 private boolean helper(int[] nums, int m, long mid) { 32 // count记录目前分割了的子数组的个数 33 int count = 1; 34 long sum = 0; 35 for (int num : nums) { 36 sum += num; 37 // 如果子数组的和超过了设定的mid,那么就分割一块,count++ 38 // 并且要把当前的这个num计算到下一个子数组里 39 if (sum > mid) { 40 sum = num; 41 count++; 42 } 43 44 // 如果分割了超过M份,就退出 45 if (count > m) { 46 return false; 47 } 48 } 49 return true; 50 } 51 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
2020-04-25 [LeetCode] 369. Plus One Linked List