找出4个正整数的列表,其总和为100

时间:2016-01-02 17:22:52

标签: algorithm sum dart combinations

我希望生成一个列表,列出4个正整数的可能列表,其总和等于100。 (加数不需要是唯一的。)

可能的示例摘录:

[
 // Using (1+1+1+97)
 [1,1,1,97],
 [1,1,97,1],
 [1,97,1,1],
 [97,1,1,1],

 // Using (2+1+1+96)
 [2,1,1,96],
 [2,1,96,1],
 [2,96,1,1],
 [96,2,1,1],

 [1,2,1,96],
 [1,2,96,1],
 [1,96,2,1],
 [96,1,2,1],

 [1,1,2,96],
 [1,1,96,2],
 [1,96,1,2],
 [96,1,1,2],

 // Using (2+2+1+95), etc...
]

这是一种有效的方法吗? (伪代码或建议很好。)

6 个答案:

答案 0 :(得分:3)

以下是适用于任意数量部件的通用解决方案:

// create(100, 4) returns the 156849 solutions
Iterable<List<int>> create(int max, int parts) sync* {
  assert(max >= parts);
  if (parts == 1) {
    yield [max];
  } else {
    for (int i = max - parts + 1; i > 0; i--) {
      yield* create(max - i, parts - 1).map((e) => e.toList()..add(i));
    }
  }
}

为4个数字提供更优化的解决方案:

// create(100) returns the 156849 solutions
Iterable<List<int>> create(int max) sync* {
  for (int a = 1; a <= max - 3; a++) { // -3 because b/c/d are >= 1
    for (int b = 1; b <= max - a; b++) {
      for (int c = 1; c <= max - a - b - 1; c++) { // -1 because d is >=1
        yield [a, b, c, max - a - b - c];
      }
    }
  }
}

答案 1 :(得分:2)

我认为最好从解决方案开始,然后将解决方案更改为其他有效的解决方案。我假设0不是有效数字。

让我们从[97,1,1,1]开始 然后我们从97减去一个,留下96。 我们有[96,1,1,1]离开1.所以我们有一个问题给我们部分答案:

“生成3个正整数的所有可能列表的列表,其总和等于4”

然后我们从96中减去一个,

“生成3个正整数的所有可能列表的列表,其总和等于5”

然后我们从95中减去一个,

“生成3个正整数的所有可能列表的列表,其总和等于6”

等。等

因为一堆问题看起来很像原始问题,我们可以重新做到从3个地方到2个地方的伎俩。 [2,1,1](留1)=&gt; “生成一个包含2个正整数的可能列表的列表,其总和等于3”,这很容易写。

现在你可以简单地编写一个很好的递归公式。

答案 2 :(得分:2)

迭代和递归解决方案: (在DartPad

上试试
void main() {
  List<List<int>> resultList1 = <List<int>>[];
    for(int i1 = 1; i1 < 98; i1++)  {
    for(int i2 = 1; (i1 + i2) < 99; i2++) {
      for(int i3 = 1; (i1 + i2 + i3) < 100; i3++) {
        for(int i4 = 1; (i1 + i2 + i3 + i4) <= 100; i4++) {
          if((i1 + i2 + i3 +i4) == 100) {
            resultList1.add([i1, i2, i3, i4]);
          }
        }
      }
    }
  }
//  print(resultList1);
  print(resultList1.length);
  final int elementCount = 4;
  final int target = 100;
  final List<List<int>> resultList2 = <List<int>>[];
  sum(elementCount, target, resultList2, [0, 0, 0, 0], 0);
//  print(result);
  print(resultList2.length);
}

void sum(int elementCount, int target, List<List<int>> result, List<int> values,
    int curPos) {
  for (int i = values[curPos] + 1; i <= target - curPos; i++) {
    // debugging only
//    if(curPos == 0) {
//      print(i);
//    }
    // end debugging only
    values[curPos] = i;
    if (curPos == elementCount - 1) {
      if (values.reduce((int a, int b) => a + b) == 100) {
//        print(values);
        result.add(values.toList());
      }
    } else {
      sum(elementCount, target, result, values, curPos + 1);
    }

    for(int j = curPos + 1; j < values.length; j++) {
      values[j] = 0;
    }
  }
}

结果包含[1,1,1,97][97,1,1,1]的156849个元素。 递归版本支持可变数量的元素和可变总和目标值。例如,通过调用它来:

  final int elementCount = 3;
  final int target = 50;
  final List<List<int>> resultList2 = <List<int>>[];
  sum(elementCount, target, resultList2, [0, 0, 0], 0);

答案 3 :(得分:1)

我认为最直接的方法是使用3个循环。

resultList = []
for a from 1 to 97:
  for b from 1 to 97:
    for c from 1 to 97:
      d = 100-a-b-c
      if d > 0:
        resultList.append([a,b,c,d])

答案 4 :(得分:1)

这是Python中的一个简单解决方案,它以字典顺序生成所有可能的结果:

resultList = []
for a in xrange(1,98):
    for b in xrange(1,98):
        for c in xrange(1,98):
            d = 100 - a - b - c
            if d > 0 and a <= b <= c <= d:
                resultList.append([a,b,c,d])

结果列表有7153个条目,以[1,1,1,97]开头,以[25,25,25,25]结尾。您可以在 http://ideone.com/8m7b1h运行该计划。

答案 5 :(得分:0)

递归方法:

MakeSum(Sum, NItems, ResultList)
  if NItems = 1
    output ResultList + [Sum]
  else
     for i = 1 to Sum - NItems + 1
        MakeSum(Sum - i, NItems - 1, ResultList + [i])