贪心优化与回溯剪枝:求解最小步数凑零的整数减法算法

夜静姑娘_6264

夜静姑娘_6264

2026-06-26

494人浏览

原创

贪心优化与回溯剪枝:求解最小步数凑零的整数减法算法

本文介绍一种结合贪心策略与回溯剪枝的高效算法,用于从给定起始整数出发,仅使用指定组件集合中的数值进行减法操作,以最少次数逼近(或恰好达到)零;适用于硬币找零类变体问题,兼顾最优性与实用性。

本文介绍一种结合贪心策略与回溯剪枝的高效算法,用于从给定起始整数出发,仅使用指定组件集合中的数值进行减法操作,以最少次数逼近(或恰好达到)零;适用于硬币找零类变体问题,兼顾最优性与实用性。

该问题本质是有界整数线性组合的余数最小化问题:给定目标值 position 和正整数集合 components,寻找非负整数系数 x₀, x₁, ..., xₖ₋₁,使得
$$ \text{remainder} = \left| \text{position} - \sum_{i=0}^{k-1} x_i \cdot \text{components}[i] \right| $$
尽可能小,且在所有最小余数解中,总操作数 $\sum x_i$ 最小。

直接暴力枚举所有组合时间复杂度为 $O\big((\frac{\text{position}}{\min(\text{components})})^k\big)$,不可接受。所给参考实现采用降序排序 + 深度优先回溯 + 早停剪枝,显著提升实际性能:

  • 预处理:将 components 升序排序后逆序遍历(即从最大值开始),优先尝试“大步削减”,符合贪心直觉;
  • 剪枝核心:
    • 对当前组件 value,最多可选 Math.floor(rest / value) 次,记为 max;
    • 若当前为最后一个组件(col === 0),则只需尝试 max 次(因减少次数只会增大余数);
    • 否则尝试 max 到 0 的所有可能,但一旦找到 rest === 0 的解,立即返回——这是最优解(余数为 0 且步数相对最少,因高位已优先取满);
    • 每层递归维护当前最优解 best(余数最小,相同时步数最少),若子树无法超越 best.rest,可提前终止(代码中隐含于 item.rest

以下是优化后的生产就绪版实现(含注释、类型提示与边界防护):

元象XChat
元象XChat

元象XChat是一款AI大模型工具,元象XVERSE大模型驱动的AI聊天助手。

下载
/**
 * 寻找用 components 中数字减去 position 后的最小非负余数,
 * 并返回对应各组件使用次数及最终余数。
 * @param {number[]} components - 正整数数组,无重复推荐
 * @param {number} position - 非负整数起点
 * @returns {{remainder: number, counts: Record<number number>, totalSteps: number}}
 */
function minimizeRemainder(components, position) {
  if (position  !Number.isInteger(x) || x  b - a); // 降序:先试大数
  const state = { remainder: position, counts: {}, totalSteps: 0 };

  function backtrack(idx, rest, stepsSoFar) {
    // 剪枝1:若当前余数已为0,直接返回(全局最优)
    if (rest === 0) return { remainder: 0, counts: { ...state.counts }, totalSteps: stepsSoFar };

    // 剪枝2:已遍历完所有组件,返回当前状态
    if (idx >= uniqueSorted.length) {
      return { remainder: rest, counts: { ...state.counts }, totalSteps: stepsSoFar };
    }

    const value = uniqueSorted[idx];
    const maxUse = Math.floor(rest / value);
    let best = { remainder: rest, counts: { ...state.counts }, totalSteps: stepsSoFar };

    // 从大到小尝试使用次数(贪心倾向),利于早发现 remainder=0
    for (let use = maxUse; use >= 0; use--) {
      const newRest = rest - use * value;
      const newSteps = stepsSoFar + use;

      // 剪枝3:若新余数已大于当前最优余数,且use>0,则后续更小use只会让余数更大 → 跳过
      if (newRest > best.remainder && use > 0) continue;

      // 更新临时状态
      if (use > 0) state.counts[value] = use;
      else delete state.counts[value];

      const candidate = backtrack(idx + 1, newRest, newSteps);

      // 更新最优解:优先余数小,余数相同时步数少者优
      if (
        candidate.remainder <p><strong>关键注意事项:</strong>  </p>
<ul>
<li>✅ <strong>适用场景</strong>:当 components 规模较小(≤10)、position 中等(≤10⁵)时,该回溯+剪枝法远优于纯暴力,且能保证全局最优;  </li>
<li>⚠️ <strong>NP-难提示</strong>:该问题属于整数规划范畴,严格最优解在一般情况下是 NP-难的;若 components 很大或 position 极高(如 10⁹),建议改用动态规划(空间换时间,需 O(position) 空间)或近似算法(如完全背包的贪心启发式);  </li>
<li>? <strong>鲁棒性增强</strong>:生产环境应增加输入校验、超时保护(如递归深度限制)及缓存(对重复 position/components 组合);  </li>
<li>? <strong>扩展方向</strong>:若允许负系数(即加减双向操作),则转化为扩展欧几里得算法求解线性丢番图方程,复杂度降至 $O(k \log \max(\text{components}))$。</li>
</ul>
<p>综上,本算法在保持正确性的前提下,通过<strong>逆序贪心驱动 + 余数主导剪枝 + 零余数早停</strong>三大策略,在实践中达成效率与精度的良好平衡,是解决此类“最小步数逼近零”问题的推荐方案。</p></number>
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

2023.08.14

5436

4

C++运算符基础入门
C++运算符基础入门

本专题详细讲解了C++运算符的类型、语法与使用方法,涵盖算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符及其他特殊运算符,并通过代码示例解析优先级与结合性。

2026.10.09

0

11

PixPix官网入口合集
PixPix官网入口合集

本专题汇总了PixPix官网在线使用入口及平台功能详解,涵盖文生图、图生图、AI图片编辑、AI视频创作等核心能力,并整理了AI爆款图片复刻、商品套图、详情页生成、视频变清晰与去水印等电商专项工具的使用教程。同时收录了PixPix MCP接入Codex、Claude Code等主流Agent的操作指南,助您一站式完成AI图片与视频创作。

2026.10.09

0

11

FrankenPHP集成Laravel详细教程
FrankenPHP集成Laravel详细教程

本专题提供FrankenPHP集成Laravel的详细配置指南,全面解析运行原理、开发环境搭建、Caddyfile配置、Octane工作模式、数据库连接、队列任务、定时任务和生产环境优化,解决部署过程中常见的报错与兼容性问题。

2026.10.08

60

20

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

2026.09.30

160

10

LLVM RISC-V参数配置教程
LLVM RISC-V参数配置教程

本专题介绍LLVM对RISC-V基础ISA和扩展的支持方式,涵盖RV32、RV64、标准扩展、实验性扩展、厂商扩展、-menable-experimental-extensions和版本差异。

2026.09.30

140

14

LLVM IR中间表示入门指南
LLVM IR中间表示入门指南

本专题整理LLVM IR的核心概念,包括中间表示作用、模块结构、函数、基本块、SSA形式、类型系统和常见语法,帮助新手理解LLVM编译流程中的关键层。

2026.09.30

100

12

PDF转图片方法
PDF转图片方法

需要把 PDF 页面用于上传、预览、分享或图片归档时,PDF 转图片方法专题整理 JPG/PNG 格式选择、逐页导出、清晰度设置、批量下载和结果检查等流程,帮助用户稳定完成 PDF 图片化处理。

2026.09.30

100

26

PixTV AI视频生成与无限画布创作
PixTV AI视频生成与无限画布创作

PixTV专题整理AI视频与视觉内容创作相关功能使用教程,涵盖AI生图、视频生成、无限画布、多模型创作、素材管理、声音音乐及视频剪辑等功能,帮助用户快速掌握PixTV从创意到成片的完整制作方法。

2026.09.29

120

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习