
本文介绍一种基于贪心思想的数组分组方法:遍历原数组,逐个累加元素到当前组,一旦加入后总和超过20则开启新组;最终生成多个子数组,每组元素和 ≤ 20,且尽可能紧凑(不回溯、不优化全局解)。适用于文件合并、资源打包等场景。
本文介绍一种基于贪心思想的数组分组方法:遍历原数组,逐个累加元素到当前组,一旦加入后总和超过20则开启新组;最终生成多个子数组,每组元素和 ≤ 20,且尽可能紧凑(不回溯、不优化全局解)。适用于文件合并、资源打包等场景。
在处理带权重的数据(如文件大小,单位 MB)时,常需将连续元素“打包”成若干组,要求每组总权重不超过上限(例如 20),同时保持原始顺序、尽量减少分组数量——这并非经典的 NP 难子集和问题,而是一个在线贪心分组(greedy bin packing, sequential variant)问题。关键在于:不跳过元素、不重排顺序、仅从前向后扫描,动态维护当前组,并在即将超限时新建分组。
下面提供一个清晰、可读性强且符合函数式风格的实现方案(使用 Array.prototype.reduce 模拟递归累积逻辑):
const add = (a, b) => a + b;
// 创建分组函数工厂:接收一个比较函数,决定是否允许加入当前组
const groupByThreshold = (isAcceptable) => (groups, value) => {
const lastGroup = groups[groups.length - 1];
const currentSum = lastGroup.reduce(add, 0);
// 若当前组为空,或加入 value 后仍满足条件,则追加;否则新建组
if (!lastGroup || isAcceptable(currentSum + value)) {
lastGroup.push(value);
} else {
groups.push([value]);
}
return groups;
};
// 示例数据:模拟文件大小(MB)
const files = [3, 8, 9, 2, 7, 5, 6, 5, 3, 11, 9, 17, 6, 5, 8, 4, 2, 7, 9, 12, 5, 16, 4];
const MAX_SIZE = 20;
// 分组策略1:严格小于20( sum sum <p>✅ <strong>核心逻辑说明</strong>: </p>
- 初始
groups = [[]],即一个空组; - 对每个
value,计算当前最后一组的和currentSum; - 若
currentSum + value ≤ 20,则push(value);否则push([value])开启新组; - 此过程天然保持原始顺序,时间复杂度 O(n),空间复杂度 O(n)。
⚠️ 注意事项:
- 该算法是贪心而非最优:它不尝试回溯或调整前面分组来容纳更大后续元素(如把
[9]和[2,7,5]合并为[2,7,5,9]是不允许的,因顺序不可逆); - 若需全局最优分组(最少组数),应使用动态规划或启发式算法(如 first-fit decreasing),但会牺牲顺序性与实时性;
- 实际文件合并中,建议额外校验单个元素是否 ≤ 20(否则无法放入任何组),可提前抛出错误或过滤异常项。
总结:对于按序打包、实时响应、轻量级约束的场景(如前端批量上传切片、日志归档压缩),这种基于 reduce 的贪心分组简洁高效、易于理解和维护,是工程实践中的优选方案。










