我正在寻找一种可用于组合数组中的值的算法,以尽可能接近“另一个值”。
例如,我想要找出给出结果结果的组合的数字是2.5。我的数组是[0.5, 1.0, 1.5, 2.0, 3.0]
。在这种情况下,组合为2.0+0.5
。
2.7将产生相同的组合(2.5是最接近的),而3.7将产生3.0+0.5
而7.0将是3.0+3.0+1.0
。
我一直在阅读不同的算法以创建可用的组合等 - 例如这一个:https://codereview.stackexchange.com/questions/7001/better-way-to-generate-all-combinations但是,我很难编写一个允许使用多个相同值的函数时代(就像我的7.0的例子)。这使得组合的数量非常大。
任何有好榜样的人都藏了起来?或者有任何指示要给?
修改 @zkar向我讲述了“背包问题”。我可以补充说,对于我的例子,追求的值在指定的范围内(1.0和10.0) - 这在某种程度上限制了组合。
答案 0 :(得分:1)
您的问题是Coin Problem和Knapsack Problem
的混合如果仅使用硬币一次:
给定一组值S,n = | S |,m:近似值
DEFINE BEST = { }
DEFINE SUM = 0
DEFINE K = 0
WHILE S IS NOT EMPTY DO
K = K + 1
FIND MIN { Si : |(SUM+Si) - m| is minimal }
ADD TUPLE < Si, |(SUM+Si) - m|, K > to BEST
SUM = SUM + Si
REMOVE Si from S
END-FOR
RETURN BEST
该算法在时间:O(| S | 2 )~O(n 2 )
中运行Set BEST将为每个K:1..n
提供n个解决方案代表K:你在那个阶段有最佳选择
找到完整的解决方案:
GIVEN BEST = { < COIN:X, DISTANCE:Y, DEGREE:K > }
DEFINE SOLUTION = { }
Y" = MINIMUM Y IN BESTi.Y for i: 1..n
KEEP ADDING BESTj.X to SOLUTION UNTILL BESTj.Y = Y" FOR j: 1..n
如果可以重复使用硬币:
DEFINE SOLUTION = { }
DEFINE SUM = 0
LESS = { Si : Si < m }
SORT LESS IN DESCENDING ORDER
FOR Li in LESS DO
WHILE (SUM+Li) <= m DO
SUM = SUM + Li
ADD Li TO SOLUTION
END-WHILE
IF SUM = m THEN BREAK-FOR
END-FOR
RETURN SOLUTION
在JavaScript中:
function coinProblem (var coins, var value)
{
var solution = new Array();
var sum = 0;
var less = new Array();
for (var i in coins)
if (i <= value)
less.push(i);
// sort in descending order
less.sort();
less.reverse();
for (var i in less)
{
while ((sum+i) <= value)
{
solution.push(i);
sum = sum + i;
}
if (sum == value) break;
}
return solution;
}
答案 1 :(得分:1)
您可以尝试这种简单的算法(JSFiddle demo):
/**
* @param src {Array} List of available values
* @param val {Number} Target value
* @returns {Array}
*/
function get_combinations(src, val)
{
var result = [];
var source = src.slice();
source.sort();
while (val > 0)
{
for (var i = source.length - 1; i >= 0; i--)
{
if (source[i] <= val || i == 0)
{
val = val - source[i];
result.push(source[i]);
break;
}
}
}
return result;
}