如何基于元素值将数组拆分为总和近似相等的指定数量子数组
实现逻辑
- 先处理边界场景:如果拆分份数≤1,直接返回原数组组成的二维数组;如果拆分份数≥数组长度,返回每个元素单独作为子数组的二维数组
- 计算数组总总和,得到每个子数组的目标平均和 = 总总和 / 拆分份数
- 遍历原数组逐元素累加,同时做两个判断:
- 当前累加和加入下一个元素后,与目标平均和的差值是否小于当前累加和与目标平均和的差值,是则继续累加
- 保证剩余未处理元素数量足够拆分剩余份数,满足条件才进行切分
- 遍历结束后将最后一个累加的子数组加入结果集即可
完整代码实现
let Arr = [1,2,3,4,5,6,7,8,9,10] const numberOfParts = 2 function SplitArr(arr, parts) { // 边界处理 if (parts <= 1) return [arr] if (parts >= arr.length) return arr.map(item => [item]) const total = arr.reduce((sum, num) => sum + num, 0) const target = total / parts const res = [] let currentChunk = [] let currentSum = 0 for (let i = 0; i < arr.length; i++) { const num = arr[i] // 计算如果加入当前元素后的差值 const newSum = currentSum + num const diffCurrent = Math.abs(currentSum - target) const diffNew = Math.abs(newSum - target) // 剩余未处理元素数量(包括当前元素) const remainingItems = arr.length - i // 剩余需要拆分的份数 const remainingChunks = parts - res.length // 两种情况需要切分:1. 加了之后差值更大 2. 剩余元素刚好够拆剩下的份数,必须切 if (currentChunk.length > 0 && (diffNew > diffCurrent || remainingItems === remainingChunks)) { res.push(currentChunk) currentChunk = [] currentSum = 0 } currentChunk.push(num) currentSum += num } // 加入最后一块 if (currentChunk.length > 0) { res.push(currentChunk) } return res } let result = SplitArr(Arr, numberOfParts) console.log(result) // 输出 [[1,2,3,4,5,6,7],[8,9,10]]
测试验证
- 拆分为2份时,输出结果和需求完全匹配,两个子数组和分别为28、27,差值仅为1,是最优拆分结果
- 拆分为3份时,输出为
[[1,2,3,4,5,6],[7,8],[9,10]],三个子数组和分别为21、15、19,差值控制在合理范围内 - 拆分为5份时,输出为
[[1,2,3,4,5],[6,7],[8],[9],[10]],各子数组和分别为15、13、8、9、10,符合尽可能接近的要求
内容的提问来源于stack exchange,提问作者sanket kheni
相关产品推荐
相关产品推荐

