[英]Finding all possible combinations of numbers to reach a given sum with zeroes and repetitions
[英]Finding all possible combinations of positive and negative numbers that equal a given sum
如果你想看看有多少种方法可以组合从 1 到 N 的数字,通过使用加法或减法,你最终会得到等于给定目标数字的组合,你会怎么做。
关于这个主题找到所有可能的数字组合以达到给定的总和,我无法以能够实现我的结果的方式修改它,所以我决定改为询问。
示例:(假设 N = 8。如果我创建以下从 1 到 N 的数组,我将如何解决这个问题。不要多次使用每个数字。)
结果:
这里是一个递归函数,它将打印所有有效的组合,以及那些无效的组合。
// This code can be improved a lot, but i wrote it in the way that i believe it is easier to read and understand what it does.
using System;
namespace algorithm_simple_csharp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Working on it!");
int[] allNumbers = new int[] {1,2,3,4};
int desiredSum = 0;
// We will create two trees, one with a positive first number, and the other one with a negative one
// Positive tree
int initIndex = 0;
OperationTreeNode firstPositiveNode = new OperationTreeNode
{
parentNode = null,
currentNumber = allNumbers[initIndex],
accumulativeSum = allNumbers[initIndex],
operation = "+"
};
int totalSolutionsPositiveFirst = ApplyNumber(firstPositiveNode, allNumbers, initIndex + 1, desiredSum);
// Negative tree
OperationTreeNode firstNegativeNode = new OperationTreeNode
{
parentNode = null,
currentNumber = -allNumbers[initIndex],
accumulativeSum = -allNumbers[initIndex],
operation = "-"
};
int totalSolutionsNegativeFirst = ApplyNumber(firstNegativeNode, allNumbers, initIndex + 1, desiredSum);
// Print all solutions found with both trees
Console.WriteLine("Total soltions: " + (totalSolutionsPositiveFirst + totalSolutionsNegativeFirst));
}
// This function will take care of the next number we should apply: allNumbers[index]
// If there are still numbers to apply, It will create two nodes, one for + allNumbers[index] and one for - allNumbers[index]
static int ApplyNumber(OperationTreeNode currentNode, int[] allNumbers, int index, int desiredSum)
{
// The base case, There are no more numbers to cover.
// In that case we evaluate if the last node is equal to desiredSum or not
if(index > allNumbers.GetUpperBound(0))
{
if(currentNode.accumulativeSum == desiredSum)
{
Console.WriteLine(currentNode.BranchToString() + " = " + currentNode.accumulativeSum + " <--- THIS ONE");
return 1;
}
Console.WriteLine(currentNode.BranchToString() + " = " + currentNode.accumulativeSum);
return 0;
}
// If it is not the last node, then we create two child nodes of the current node.
// First we evaluate what happens if we apply a + to the next number...
OperationTreeNode plusNode = new OperationTreeNode
{
parentNode = currentNode,
currentNumber = allNumbers[index],
accumulativeSum = currentNode.accumulativeSum + allNumbers[index],
operation = "+"
};
int totalSolutionsWithPlus = ApplyNumber(plusNode, allNumbers, index +1, desiredSum);
// Now we evaluate what happens if we apply a - to the next number...
OperationTreeNode minusNode = new OperationTreeNode
{
parentNode = currentNode,
currentNumber = allNumbers[index],
accumulativeSum = currentNode.accumulativeSum - allNumbers[index],
operation = "-"
};
int totalSolutionsWithMinus = ApplyNumber(minusNode, allNumbers, index +1, desiredSum);
// The total number of solutions we found is the sum of the solutions of both sub-trees
return totalSolutionsWithPlus + totalSolutionsWithMinus;
}
}
public class OperationTreeNode
{
public int accumulativeSum = 0;
public OperationTreeNode parentNode = null;
public int currentNumber = 0;
public string operation;
public string BranchToString()
{
if(parentNode == null)
{
return $"{this.currentNumber} ";
}
return $"{parentNode.BranchToString()} {this.operation} {this.currentNumber} ";
}
}
}
Working on it!
1 + 2 + 3 + 4 = 10
1 + 2 + 3 - 4 = 2
1 + 2 - 3 + 4 = 4
1 + 2 - 3 - 4 = -4
1 - 2 + 3 + 4 = 6
1 - 2 + 3 - 4 = -2
1 - 2 - 3 + 4 = 0 <--- THIS ONE
1 - 2 - 3 - 4 = -8
-1 + 2 + 3 + 4 = 8
-1 + 2 + 3 - 4 = 0 <--- THIS ONE
-1 + 2 - 3 + 4 = 2
-1 + 2 - 3 - 4 = -6
-1 - 2 + 3 + 4 = 4
-1 - 2 + 3 - 4 = -4
-1 - 2 - 3 + 4 = -2
-1 - 2 - 3 - 4 = -10
Total soltions: 2
它创建了一棵树。 树的每个节点都是一个OperationTreeNode
类型的对象,表示一个数字及其操作。 例如:+1 和 -1 是两个OperationTreeNode
当您达到最后一个数字时, ApplyNumber
将评估节点是否等于desiredSum
。
ApplyNumber
返回子树找到的ApplyNumber
据我所知,如果我理解了这个问题,你需要一个for
循环,因为如果你有一个数字n
,那么加或减的数字有无限组合等于n
,所以你需要一个数字,如果达到将停止该过程。 如果您需要多个数字(例如 3+10+1=14),您需要更多的循环。 这将是我要走的路:
int l = 50;//my limit
int n = 14;//my number
for(int i = 0; i < l; i++)
{
for(int j = 0; j < l; j++)
{
if ( i + j == n )
{
//Do whatever you want
Console.WriteLine("{0} = {1} + {2}", n, i, j);
}
if ( i - j == n )
{
//Do whatever you want
Console.WriteLine("{0} = {1} - {2}", n, i, j);
}
}
}//Repeat for negative numbers
希望这会有所帮助。
迭代,有多少种方法可以达到一个目标。
using System;
class Program
{
static void Main()
{
Console.WriteLine(C(0));
int[] a = { 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144 };
Console.Write(C(0, a)); Console.Read();
}
static int C(int t) // ±1 ± 2 ± 3 ± 4 == 0
{
int c = 0, s = 0;
for (int n = 0; n < 16; n++)
{
if ((n & 1) == 0) s -= 1; else s += 1;
if ((n & 2) == 0) s -= 2; else s += 2;
if ((n & 4) == 0) s -= 3; else s += 3;
if ((n & 8) == 0) s -= 4; else s += 4;
if (s == t) c++; s = 0;
} return c;
}
static int C(int t, int[] a)
{
int c = 0, s = 0, i, j = a.Length, n, m = 1 << j;
for (n = 0; n < m; n++)
{
for (i = 0; i < j; i++)
if ((n & 1 << i) == 0) s -= a[i]; else s += a[i];
if (s == t) c++; s = 0;
} return c;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.