在C

时间:2016-10-21 09:58:30

标签: c algorithm

我在大学接受了一项任务,我们必须解决以下问题:

在这个问题中,我们考虑给定正整数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

现在我知道我应该想要创建一个带循环和递归的二叉树。但是我们还没有完成指针的工作,我真的不知道从哪里开始或者如何构建像这样的二叉树。也许有一个技巧,程序不必如此复杂,但我没有找到捷径。有什么建议吗?

3 个答案:

答案 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作为指向数组的指针传递,这使我们不会在函数调用期间将整个数组复制为参数。

这个想法不是关于构建实际的二叉树。而是设计一个递归树,它在每个级别发出两个分支(一个用于'+',一个用于' - '),直到达到有效/无效的解决方案(叶子)。