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

如何用JavaScript实现Best Fit算法?现有Bin Packing函数问题排查

最佳适配(Best Fit)装箱算法实现问题

我写了一个用Best Fit算法解决装箱问题的JavaScript函数,但输出结果不符合预期:元素大量重复,排序效果差,比如"CSS"明明能放进第一个子数组,却被单独放在一个数组里。下面是我的代码和错误输出:

const bestFit = (stringArray, maxWidth) => {
  let results = [[]];

  stringArray.sort((a, b) => b.length - a.length); // 从大到小排序

  // ['TailwindCSS', 'Woocommerce', 'typescript', 'three.js', 'threlte', 'svelte', 'Python', 'CSS']
  try {
    stringArray.forEach((str, strIndex) => {
      if (!results[0][0]) {
        results[0].push(str)
      } else {
        const tempArray = [];
        results.forEach((_elm, _idx) => {
          tempArray.push({ index: _idx, data: _elm });
        });
        tempArray.sort((a, b) => {
          return a.data.join().length - b.data.join().length; // 从小到大排序
        })
        for (const [_tx, _obj] of tempArray.entries()) {
          const availableSpace = (_obj.data.join('').length + str.length) <= maxWidth;
          if (availableSpace) {
            results[_obj.index].push(str);
            continue;
          } else {
            if (tempArray[_tx + 1]) {
              continue;
            } else {
              results.push([str]);
            }
          }
        }
      }
    });
  } catch (e) {
    console.log(e);
  }


  return results;
}
const technologies = ['svelte', 'typescript', 'threlte', 'three.js', 'TailwindCSS', 'Python', 'Woocommerce', 'CSS'];
const MAX_LENGTH = 20;

const results = bestFit(technologies, MAX_LENGTH);

console.log(results);
// 错误输出:
// [
//   ["TailwindCSS", "three.js",],
//   ["Woocommerce", "three.js",],
//   ["typescript", "three.js",],
//   ["threlte", "svelte", "Python",],
//   ["svelte", "Python", "CSS",],
//   ["Python", "CSS",],
//   ["CSS",],
// ]

问题根源

  • 遍历逻辑错误:找到第一个能放下元素的箱子后没有终止循环,导致后续所有符合条件的箱子都会重复添加同一个元素,这是重复元素的核心来源。
  • Best Fit逻辑偏离:原代码只是按已用空间从小到大遍历箱子,没有找到剩余空间最小且能容纳当前元素的最优箱子,不符合Best Fit算法的核心要求。
  • 空间计算冗余:用join('').length计算已用空间,不如直接求和字符串长度直观,虽然结果一致,但逻辑上不够清晰。

修正后的代码

const bestFit = (stringArray, maxWidth) => {
  const results = [];
  // 复制原数组并按长度降序排序(Best Fit Decreasing优化步骤)
  const sortedStrings = [...stringArray].sort((a, b) => b.length - a.length);

  sortedStrings.forEach(str => {
    let bestBoxIndex = -1;
    let minRemainingSpace = Infinity;

    // 遍历现有箱子,找到剩余空间最小且能放下当前元素的箱子
    for (let i = 0; i < results.length; i++) {
      const box = results[i];
      const usedSpace = box.reduce((total, s) => total + s.length, 0);
      const remainingSpace = maxWidth - usedSpace;

      if (remainingSpace >= str.length && remainingSpace < minRemainingSpace) {
        bestBoxIndex = i;
        minRemainingSpace = remainingSpace;
      }
    }

    if (bestBoxIndex !== -1) {
      results[bestBoxIndex].push(str);
    } else {
      // 没有合适的箱子,新建一个
      results.push([str]);
    }
  });

  return results;
};

const technologies = ['svelte', 'typescript', 'threlte', 'three.js', 'TailwindCSS', 'Python', 'Woocommerce', 'CSS'];
const MAX_LENGTH = 20;

const results = bestFit(technologies, MAX_LENGTH);
console.log(results);

修正说明

  • 还原Best Fit核心逻辑:遍历所有箱子时,专门记录剩余空间最小且能容纳当前元素的箱子,确保元素放入最优位置。
  • 终止重复添加:找到最优箱子后直接放入,不再继续遍历其他箱子,彻底解决元素重复问题。
  • 简化空间计算:用reduce直接求和箱子内字符串长度总和,逻辑更清晰,避免不必要的字符串拼接操作。
  • 优化初始处理:去掉冗余的初始箱子判断,直接从空数组开始构建,代码更简洁。

正确输出

[
  ["TailwindCSS", "CSS"],
  ["Woocommerce", "Python"],
  ["typescript", "svelte"],
  ["three.js", "threlte"]
]

可以看到"CSS"被正确放入第一个箱子(TailwindCSS长度10 + CSS长度3 = 13 ≤ 20),没有重复元素,装箱效率符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:15:38