当前位置: 首页 > news >正文

LeetCode 410 - 分割数组的最大值

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码详解:
    • 示例测试及结果
      • 运行结果:
      • 解释:
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

今天要聊的题是 LeetCode 410:分割数组的最大值(Split Array Largest Sum)
这题的核心是——如何在把数组拆成 k 段之后,让这些段的“最大和”尽可能小。

换句话说,这是一道非常经典的“二分 + 贪心”混合问题。看起来像是要枚举所有分法,但实际上我们可以通过“最大和上限”来二分搜索答案,找到最优解。

这类题在项目中也挺常见,比如你要把一批任务分配给 k 台服务器,每台机器的任务量不能太悬殊,我们就希望找到“最平衡”的那种分法。

描述

题目是这样说的:

给定一个非负整数数组 nums 和一个整数 k,我们需要把 nums 拆成 k 个非空连续子数组,使得这 k 个子数组的“和的最大值”尽量小。

返回这个最小的“最大和”。

比如:

输入:nums = [7,2,5,10,8], k = 2
输出:18

这里最优的拆法是 [7,2,5][10,8]
第一个子数组的和是 14,第二个是 18,所以“最大和”是 18。
而且这 18 是所有拆法中最小的可能值。

题解答案

这题的暴力解法显然行不通,因为所有拆法的组合太多了。
一个更聪明的思路是:
我们可以“假设”当前能接受的最大和是 x,然后去判断能不能把数组拆成 ≤ k 段,使得每段的和都 ≤ x

如果能做到,那说明 x 还可以更小;
如果做不到,那说明 x 太小了,得放宽。

这样我们就能用“二分法”去搜索最小可行的 x
听起来像 DP,但其实用贪心就能实现判断逻辑。

题解代码分析

下面是完整的 Swift 代码,可以直接在 LeetCode Playground 或 Xcode 里运行:

import Foundationclass Solution {func splitArray(_ nums: [Int], _ k: Int) -> Int {var left = nums.max() ?? 0   // 下界:至少要能装得下最大的单个元素var right = nums.reduce(0, +) // 上界:所有元素相加(全部不拆的情况)var result = right// 二分查找最小的“最大子数组和”while left <= right {let mid = (left + right) / 2if canSplit(nums, k, mid) {result = midright = mid - 1 // 尝试更小的上限} else {left = mid + 1 // 当前上限太小,不够装}}return result}// 判断能否用 <= k 段来满足“每段和 ≤ maxSum”private func canSplit(_ nums: [Int], _ k: Int, _ maxSum: Int) -> Bool {var count = 1var currentSum = 0for num in nums {if currentSum + num > maxSum {// 需要新开一段count += 1currentSum = numif count > k { return false } // 拆的段太多了,不行} else {currentSum += num}}return true}
}

代码详解:

  1. 边界初始化:

    • left 设为 nums 中的最大值(任何分法都得能装下最大的元素)。
    • right 是数组总和(最极端的情况:不拆分)。
  2. 二分搜索逻辑:

    • 每次取 mid 作为当前假设的“最大和上限”。
    • 调用 canSplit() 判断在这个上限下能不能拆成 k 段。
    • 如果能,那我们试试看更小的上限;
    • 如果不能,那说明这上限太紧,得放大。
  3. canSplit 函数:
    用一个简单的贪心法,从左到右累加,一旦超出 maxSum 就“另开一段”。
    如果段数超过 k,说明当前上限不行。

这段代码思路非常简洁,逻辑清晰,不需要 DP 就能在 O(n log(sum)) 的时间内完成判断。

示例测试及结果

我们来手动测试几个例子。

let solution = Solution()print(solution.splitArray([7,2,5,10,8], 2))  // 输出: 18
print(solution.splitArray([1,2,3,4,5], 2))   // 输出: 9
print(solution.splitArray([1,4,4], 3))       // 输出: 4

运行结果:

18
9
4

解释:

  • [7,2,5,10,8] 拆成 [7,2,5] + [10,8],最大和为 18;
  • [1,2,3,4,5] 最优拆法是 [1,2,3] + [4,5],最大和 9;
  • [1,4,4] 拆成 [1], [4], [4],每段最大和是 4。

这些结果完全符合预期。

时间复杂度

  • 二分查找次数: 取决于搜索区间 [max(nums), sum(nums)],大约是 log(sum(nums))
  • 每次检查复杂度: O(n),因为要遍历一遍数组判断能否拆分。

综合下来,总复杂度是:

O(n · log(sum(nums)))

这个效率非常不错,即便 nums 长度是 1000,也能轻松通过。

空间复杂度

代码里没有使用额外的数据结构,除了常数级变量。

空间复杂度:O(1)

所以非常节省内存。

总结

这题最重要的突破点是:不要硬拆数组,而是去猜“最大和”是多少。
通过“二分 + 贪心”,我们把一个原本爆炸级复杂的枚举问题,变成了一个可以稳定在 O(n log(sum)) 的算法。

在实际开发中,这种思路也很常见。比如:

  • 任务分配系统要尽量均衡负载;
  • 文件分块上传要控制每块的最大大小;
  • 分页加载时要动态调整每页的数据量上限。

这些都可以类比成“分割数组的最大值”问题。

如果你掌握了这种“从目标值反推结构”的思维方式,以后再遇到类似“最小化最大值”或“最大化最小值”的题,基本都能用二分思路搞定。

http://www.dtcms.com/a/545339.html

相关文章:

  • Kotlin数据结构性能全解析
  • 搜索引擎网站优化和推广方案网站建设招标合同要求
  • coco json 分类标注工具源代码
  • 重学JS-012 --- JavaScript算法与数据结构(十二)正则表达式
  • 自己做网站还是公众号爱链网中可以进行链接买卖
  • maven中properties和dependencys标签的区别
  • 商丘市有没有做网站品牌宣传网站制作
  • ArcGIS Pro 与 Python,在数据处理中该如何选择与搭配?
  • 多端大前端项目实施方案
  • 企业网站推广效果指标分析安徽圣力建设集团网站
  • 网站建设规划方案免费项目发布平台
  • 越南频段开放趋势对蜂窝物联网模组的影响分析
  • 通过gdb推进修改oracle scn
  • 行业认可丨宏集Web物联网HMI荣获CEC 2025年度编辑推荐奖
  • 网站正能量晚上不用下载免费进入运维工程师40岁以后出路
  • 网站定制公司排行榜购买网站app制作
  • LeetCode算法日记 - Day 88: 环绕字符串中唯一的子字符串
  • 发送 Prompt 指令:判断用户评价是好评还是差评
  • 高阶数据结构 --- 跳表Skiplist
  • Ansible模块分类与实战应用指南
  • 发送 Prompt 指令:请用一句话总结文本内容
  • 沧州网站seo创业 建网站
  • 临安市住房和建设局网站百度搜索引擎的原理
  • k8s rbac权限最小化实践
  • Javascript数据类型之类型转换
  • 销售拜访前的全面准备指南以及ABC推荐法
  • 优秀网站模板下载网站编程论文
  • 仓颉代码内联策略:性能优化的精密艺术
  • 欧瑞电机编码器引脚定义
  • 中国隧道空间分布