我在大学接受了一项任务,我们必须解决以下问题:
在这个问题中,我们考虑给定正整数n,形式
的加法表达式 n = 1 ± 2 ± 3 ± 4 ± ... ± n − 2 ± n − 1 ± n
例如,对于n = 5,以下两个表达式是该表单中唯一有效的表达式:
5 = 1 + 2 + 3 + 4 − 5
5 = 1 − 2 − 3 + 4 + 5
编写一个程序,在其输入上接受一个整数n(其中0 现在我知道我应该想要创建一个带循环和递归的二叉树。但是我们还没有完成指针的工作,我真的不知道从哪里开始或者如何构建像这样的二叉树。也许有一个技巧,程序不必如此复杂,但我没有找到捷径。有什么建议吗?
答案 0 :(得分:0)
我觉得自己很慷慨。我不会给你递归的答案,我会用抨击,所以如果你能自己解决这个问题并将其改为递归,我想你会学到足够的东西来欺骗自己。如果你复制这个verbatinum,你的教授会知道你被骗了。
int n = 5;
int i,j,c;
for (i=0;i<(1<<n);i++)
{
c = 0;
for (j=1;j<=n;j++)
{
if (i&(1<<(j-1))) {c+=j; printf("+%d",j); }
else { c-=j; printf("-%d",j); }
}
if (c == n) printf(" = %d\n",n);
else printf(" != %d\n",n);
}
输出是:
-1-2-3-4-5 != 5
+1-2-3-4-5 != 5
-1+2-3-4-5 != 5
+1+2-3-4-5 != 5
-1-2+3-4-5 != 5
+1-2+3-4-5 != 5
-1+2+3-4-5 != 5
+1+2+3-4-5 != 5
-1-2-3+4-5 != 5
+1-2-3+4-5 != 5
-1+2-3+4-5 != 5
+1+2-3+4-5 != 5
-1-2+3+4-5 != 5
+1-2+3+4-5 != 5
-1+2+3+4-5 != 5
+1+2+3+4-5 = 5
-1-2-3-4+5 != 5
+1-2-3-4+5 != 5
-1+2-3-4+5 != 5
+1+2-3-4+5 != 5
-1-2+3-4+5 != 5
+1-2+3-4+5 != 5
-1+2+3-4+5 = 5
+1+2+3-4+5 != 5
-1-2-3+4+5 != 5
+1-2-3+4+5 = 5
-1+2-3+4+5 != 5
+1+2-3+4+5 != 5
-1-2+3+4+5 != 5
+1-2+3+4+5 != 5
-1+2+3+4+5 != 5
+1+2+3+4+5 != 5
答案 1 :(得分:0)
如果使用递归,则无需构建二叉树。递归调用可以为你做这件事,可以这么说。
以下是原始O(2 ^ n)解决方案。
// Calculate the number of ways to get a sum of -value given the numbers ±1 to ±n.
int func(int value, int level) {
if (level == 0) {
// Base case
return (value == 0);
}
// Recursive step.
return func(value + level, level - 1) + func(value - level, level - 1);
}
int main(void) {
int level;
for (level = 0; level < 10; level++) {
printf("n=%d, reult=%d\n", func(-level, level));
}
}
答案 2 :(得分:0)
void printSolution(int* arr, int n) {
printf("1");
for(int i = 0; i < n - 1; ++i) {
if(arr[i] == -1) // '-' sign
{
printf(" - ");
}
else { // if arr[i] == 1, then '+' sign
printf(" + ");
}
printf("%d", i + 2);
}
printf(" = %d\n", n);
}
int numberofExpressionHelper(int indx, int *arr, int n, int sum) {
// base case; we end up putting all (n - 1) signs between numbers
// Now if the sum is equal to n, we get one solution
if(indx == n - 1) {
if(sum == n) {
printSolution(arr, n);
return 1;
}
return 0;
}
int ret;
ret = 0;
// putting '+' in between
arr[indx] = 1; // +
int right_operand;
right_operand = indx + 2;
// As we put '+', we add right operand with sum for next call
ret += numberofExpressionHelper(indx + 1, arr, n, sum + right_operand);
// putting '-' in between
arr[indx] = -1; // -
// As we put '-', we subtract right operand from sum for next call
ret += numberofExpressionHelper(indx + 1, arr, n, sum - right_operand);
return ret;
}
void numberofExpression(int n) {
if(n <= 0) return; // assuming given input will be greater than 0
// arr[i] will contain the sign(+ or -) between number i + 1 and i + 2
// e.g. arr[0] will contain the sign between 1 and 2
// We will keep 1 for '+' and -1 for '-' in the arr
// e.g. 1 + 2 + 3 + 4 - 5 = 5
// the corresponding arr will be [1, 1, 1, -1]
// e.g. 1 - 2 - 3 + 4 + 5 = 5
// arr = [-1, -1, 1, 1]
int arr[n];
// start sum with 1 as first element will be obviously 1
int result;
result = numberofExpressionHelper(0, arr, n, 1);
printf("Total number of expressions: %d\n", result);
}
示例:
numberofExpression(5);
输出:
1 + 2 + 3 + 4 - 5 = 5
1 - 2 - 3 + 4 + 5 = 5
Total number of expressions: 2
正如你所说,你知道递归。现在用你的IDE调试这个程序和/或尝试用笔和纸来理解程序流程,我希望你能得到这个想法。这里arr
作为指向数组的指针传递,这使我们不会在函数调用期间将整个数组复制为参数。
这个想法不是关于构建实际的二叉树。而是设计一个递归树,它在每个级别发出两个分支(一个用于'+',一个用于' - '),直到达到有效/无效的解决方案(叶子)。