You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻找最小容量N的算法:将栈元素划分为最多X个和小于N的子集

算法思路:二分查找 + 可行性验证

这是个典型的二分查找应用问题,核心思路是通过二分法缩小最小容量N的范围,同时验证每个候选N是否满足运输要求。我来一步步拆解思路:

1. 问题转化与边界确定

首先明确:因为划分必须保持元素原有顺序,这个“栈”本质上就是一个有序整数序列(我们只需要按顺序遍历元素即可,不用考虑栈的弹出操作)。我们要找最小的N,使得序列能被拆分为最多X个连续子数组,每个子数组的元素和严格小于N。

对于N的取值范围,我们可以确定两个明确的边界:

  • 左边界left:栈中最大元素的值 + 1。因为如果N小于等于最大元素,这个元素无法单独放入任何一个子集(它的和等于自身,不小于N),所以N必须至少比最大元素大1。
  • 右边界right:栈中所有元素的总和 + 1。当X=1时,我们需要把所有元素一次性运完,此时N必须大于总和,所以右边界设为总和+1足够覆盖所有情况。

2. 二分查找核心逻辑

我们通过二分查找在[left, right]范围内寻找最小的可行N:

  • 取中间值mid = (left + right) // 2,验证这个mid是否能满足“最多X趟运完”的要求。
  • 如果mid可行,说明我们可以尝试找更小的N,因此将右边界调整为mid - 1,同时记录当前mid为候选答案。
  • 如果mid不可行,说明需要更大的N,将左边界调整为mid + 1。

3. 可行性验证函数

判断某个N是否可行的逻辑非常直观:

  • 初始化当前子数组的和current_sum = 0,已用趟数count = 1(至少需要1趟)。
  • 按顺序遍历每个元素:
    • 如果current_sum + 当前元素 < N,就将该元素加入当前子数组,更新current_sum。
    • 否则,必须开启新的一趟:count += 1,并将当前元素作为新子数组的第一个元素,重置current_sum为该元素的值。
    • 如果中途count > X,直接返回False(这个N太小,无法在X趟内运完)。
  • 遍历结束后,若count <= X,返回True(这个N是可行的)。

4. 特殊情况快速处理

  • 当X等于栈中元素的个数时:最小N就是最大元素 + 1,因为每个元素单独运一趟即可。
  • 当X=1时:最小N就是所有元素总和 + 1,因为必须一次性运完所有元素,总和必须小于N。

示例演示

假设栈元素为[3,2,2,4,1],X=3:

  1. 左边界left=4+1=5,右边界right=3+2+2+4+1+1=13。
  2. 第一次取mid=9,验证后发现可以分成3趟([3,2,2], [4], [1]),可行,于是尝试更小的N,将right设为8。
  3. 取mid=6,验证后可分成[3,2], [2], [4,1](和分别为5、2、5,都小于6),可行,将right设为5。
  4. 取mid=5,验证时会发现需要4趟才能运完,不可行,于是将left设为6。
  5. 此时left>right,循环结束,最小N为6。

内容的提问来源于stack exchange,提问作者Claudinho18

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:46:52