js 一堆数字凑数算法_凑数(如何凑出若干个数中某几个数等于某一目标值?)...

本文介绍了一种在Excel中通过规划求解找出一组数字中哪些数相加等于目标值的方法,适用于财务数据分析场景。文章通过实例演示了如何使用SUMPRODUCT函数和规划求解工具,并讨论了VBA在解决此类问题中的优势和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

凑数在更深一步财务数据分析和核算中有着很重要的作用

你是否有遇到过收到的一笔款对应哪几个发票金额?一张发票对应哪几笔收款?等等其他方面需要从一堆数里凑几个数等于你要的值。

对于数字敏感的人,一些简单的可以从肉眼看到直接找出是哪几个数,但是如果对于数据稍微多一点,金额没有规律的你又怎么能轻易用肉眼找出来呢

一起学一个凑数功能吧:

规划求解

先看看在EXCEL中哪个位置

数据-模拟分析-规划求解

c01d173d6f1bea8f0da22a9f3ae29ba6.png

如何从一堆数里找出哪几个数相加等于你要的值?

看一个例子

B列有12个数,其中B1+B3+B6+B11=16368.94

28607769350bc1c9223ab2ed9ca6865d.png

如何从一堆数里找出哪几个数相加等于你要的值?

假设我们事先不知道是这几个数相加等于16368.94,那我们怎样从这12个数里面凑出是B1、B3、B6、B11的和是16368.94呢?

具体操作如下 :

1.在c1单元格输入=SUMPRODUCT(B1:B12,C1:C12)

sumproduct函数用法:

SUMPRODUCT(数组1,数组2, ...),sum是求和的意思,PRODUCT是求积,最后返回的是成绩之和。

看一个小例子:

c05c6a80fc2aec598e41b20242eff169.png

如何从一堆数里找出哪几个数相加等于你要的值?

其实就是=1*3+1*4+1*5+1*6+1*2+1*1=21

回到上面,返回的是0,因为C列为没有值

d32cb324ae8a83ecebbc1ba09ec9e92e.png

如何从一堆数里找出哪几个数相加等于你要的值?

2.点击数据-模拟分析-规划求解,弹出对话框设定相应的条件:

目标单元格是D1,下面勾选目标值在里面输入刚才的数字16368.94,可变单元格选中刚才为空值的C1到C12,添加类型CI到C12=二进制(二进制的值就是0和1)求解方法选单纯线性规划

(选择二进制是避免出现零点几等不规则小数,求解方法选单纯线性规划是明确求解方向,速度和效率更快)

如下图

5c2935eff604a923532da9d2ecb569ea.png

如何从一堆数里找出哪几个数相加等于你要的值?

保留规划求解的解

5b2e5aa515d1110cf75a216e8bc9f77b.png

如何从一堆数里找出哪几个数相加等于你要的值?

点确定后,我们看到C列有值为0和1

4512623628eeb7f93e3efa6ea3ec01da.png

如何从一堆数里找出哪几个数相加等于你要的值?

其实最后我们要求的目标值就是C列为1对应左边B列单元格值的和,刚好就是上面说的

B1、B3、B6、B11

原理就是利用数组乘积得到目标值

特别注意:规划求解求的是最佳组合,即符合条件的一种最佳方案,如果还有其他几个数的和也为目标值,是难以求出的,当然如果要求出所有的值可以借助EXCEL的重磅程序VBA来处理,给你看一下VBA设计的凑数工具更快更高效地解决凑数问题吧,看一下效果

比如说我们要从1到10里面找出所有相加等于15的结果

直接在目标值里面输入15,误差选0,组合个数选11,点击不重复求和递归就可以得到所有的结果展示在右边,如下图

0c8a29e0a15ca178f687b4f887d92709.png

如何从一堆数里找出哪几个数相加等于你要的值?

使用VBA更轻松跟快,结果更全面,后面会更新VBA相关的内容(在EXCEL里面使用VBA需要安装VBA程序)

关注我,一点一滴带你学Excel和财务实操知识

欢迎评论和转发,如有工作中实际遇到的问题,可以评论区留言,一起探讨

### JavaScript 实现高效凑数算法 为了从给定组 `[0, 4, 4, 0, 4, 0, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2]` 中找到所有加和为目标值(本例中为33)的组合,并返回这些组合以及它们对应的索引组和组,可以采用动态规划的方法。这种方法相较于暴力枚举更加高效。 #### 动态规划解决方案 通过动态规划的思想解决该问题的核心在于记录达到某个特定和的所有可能路径。具体实现如下: ```javascript function findCombinationsWithIndicesDP(nums, target) { const dp = Array.from({ length: target + 1 }, () => []); // 初始化:当目标和为0时,存在种空组合的情况 dp[0].push({ combination: [], indices: [] }); for (let i = 0; i < nums.length; i++) { const num = nums[i]; // 倒序更新以避免重复使用当前元素 for (let j = target; j >= num; j--) { if (dp[j - num].length > 0) { dp[j - num].forEach((prevCombo) => { const newCombination = prevCombo.combination.concat(num); const newIndices = prevCombo.indices.concat(i); // 添加新的组合到对应的目标和位置 dp[j].push({ combination: newCombination, indices: newIndices }); }); } } } return dp[target]; } const array = [0, 4, 4, 0, 4, 0, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2]; const targetSum = 33; console.log(JSON.stringify(findCombinationsWithIndicesDP(array, targetSum), null, 2)); ``` 此代码利用了动态规划表 `dp` 来存储到达每个可能和的所有有效组合方式。最终结果可以从 `dp[target]` 获取[^1]。 #### 关键点解析 - **状态定义**:设 `dp[j]` 表示能够组成和为 `j` 的所有组合及其索引。 - **转移方程**:对于每个数字 `num` 和其索引 `i`,如果之前已经找到了某些组合使得和为 `j-num`,那么可以通过向这些组合追加 `(num, i)` 得到新的合法组合。 - **初始化**:规定只有在没有任何数字被选入的情况下才能形成和为零的状态,即 `dp[0]` 初始包含个空组合。 - **倒序遍历**:为了避免同轮内的重复计问题,在内部循环中采取由大至小的方向进行更新操作[^2]。 相比之前的回溯法,这种方式显著降低了时间复杂度并提高了运行效率,尤其适合较大规模的据集场景下寻找最优解或多组可行解的应用需求[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值