允许数字重用的子集和

时间:2017-11-24 10:51:39

标签: javascript math subset subset-sum

我有一个正整数列表,例如15, 29, 110,以及目标44。我试图找到所有可能的组合,它们总和到目标但重要的是,集合中的数字可以多次使用,例如。

Target = 44
Result = 1x15, 1x29

Target = 307
Result = 2x110, 3x29

我找到了一个动态编程解决方案,当组合不超过每个数字的一​​个时,它可以工作。所以Target 44可以工作但不是我的307示例(返回Not Found)。

如何重复使用倍数或数字?

function subset(people, min, max)
{
  var subsets = [];
  subsets[0] = '';

  for (var person in people)
  {
    for (var s = min-1; s >= 0; --s)
    {
      if (s in subsets)
      {
        var sum = s + people[person];

        if (!(sum in subsets))
        {
          subsets[sum] = subsets[s] + ' ' + person;

          if (sum >= min && sum <= max)
          {
            return subsets[sum];
          }
        }
      }
    }
  }

  return 'Not found';
}

var p = {
   optionA:15,
   optionB:29,
   optionC:110
};
var qty = 307;
console.log(subset(p, qty, qty));

2 个答案:

答案 0 :(得分:0)

尝试这种递归解决方案:

&#13;
&#13;
function subset(people, min, max) {
	const pairs = Object.entries(people),
		results = [],
		getSum = multiplications => multiplications.reduce((sum, multiplicator, position) => 
			sum + pairs[position][1] * multiplicator, 0),
		formatResult = result => result.map(multiplications => 
			multiplications.reduce((res, multiplicator, position) => 
			(multiplicator > 0 ? res.push(`${multiplicator}x${pairs[position][1]}`) : 
				res, res), []));
	function findSums(multiplications, position) {
		let s;
		while((s = getSum(multiplications)) <= max) {
			if (s >= min) {
				results.push([...multiplications]);
			}
			if (position < pairs.length - 1) {
				const m = [...multiplications],
					nextPosition = position + 1;
				m[nextPosition]++;
				findSums(m, nextPosition);
			}
			multiplications[position]++;
		}
	}
	findSums(pairs.map(_ => 0), 0);
	return results.length > 0 ? formatResult(results) : "Not found";
}

var p = {
   optionA:15,
   optionB:29,
   optionC:110
};
var qty = 307;
console.log(subset(p, qty, qty));
&#13;
&#13;
&#13;

答案 1 :(得分:0)

以这种方式更改第二个循环:

for (var s = 0; s <= wantedSum - people[person] ; s++)

使用此方法填充subsets[] array \ list的所有条目,其中index是people[person]的倍数(而不是单个条目)。例如,对于值3,您将填写3,6,9,12 ...个条目。