如何将此函数重新实现为尾递归或以其他方式使用更少的内存?

时间:2016-10-25 04:21:57

标签: c recursion tree

我需要递归地进行以下计算。

对于1到30之间的任何n,我需要考虑从1到n的所有可能的加法或减法组合。所以,例如,如果n = 5:

1 ± 2 ± 3 ± 4 ± 5 ± 6 = ?;

我需要找到与数字本身相等的可能表达式的数量。因此,对于n = 5,只有以下两个表达式等于5:

5 = 1 + 2 + 3 + 4 − 5
5 = 1 − 2 − 3 + 4 + 5

我的方法

我想出了如何创建递归树,其中每个递归级别将添加或减去“深度”。因此,在最后的深度,节点已经有了计算的总和 - 我所要做的就是检查它们是否等于初始数。

Recursive Tree Image

这样可以正常工作,但是在数字大于n> 26时,我会遭受巨大的内存消耗,并且程序耗时太长。一点点数学就清楚了解原因。 那么我该如何优化呢?我一直试图把它变成尾递归,但它对我不起作用......当我有两个递归调用时,我根本不理解如何实现它。

这是我的代码:

树结构和创建功能

typedef struct nodes {
    unsigned int value;
    struct node* pos;
    struct node* neg;
} node;


node* addNode(int data){

    node* newNode = (node*)malloc(sizeof(node));
    newNode->value = data;
    newNode->pos = NULL;
    newNode->neg = NULL;

    return newNode;
}

构建我的树的功能

node* buildTree(int depth, int data){

    node* nNode = addNode(1);

    if(depth==n+1){
        if(data == n) {
            result++;
        }
        return nNode;
    }

    else{
        nNode->pos = buildTree(depth+1,data+depth);
        nNode->neg = buildTree(depth+1,data-depth);
        return nNode;
    }
}

全球范围变量&主

int result = 0;
int n;

int main(int argc, char **argv)
{
    scanf("%i",&n);
    buildTree(2,1); //build tree starting with recursion depth = 2, first node value = 1.
    printf("%i\n",result);

    return 0;
}

请帮忙 - 我已经坚持了很长时间。

1 个答案:

答案 0 :(得分:1)

我认为你不需要树。

一些简单的递归应该这样做:

#include <stdio.h>

void f(int current_sum, int current_depth, int target_depth)
{
    if (current_depth > target_depth)
    {
            // Here you have the final result for this path
        printf("%d\n", current_sum);
        return;
    }
    f(current_sum+current_depth, current_depth+1, target_depth);
    f(current_sum-current_depth, current_depth+1, target_depth);
}

int main(void) {
    f(0, 1, 3);   // I use n=3
    return 0;
}
  

输出:

6
0
2
-4
4
-2
0
-6

提示:通过注意后半部分数字是上半部分的负数,您可以大大提高运行时性能。使用类似的东西:

    f(current_sum+current_depth, current_depth+1, target_depth);
    if (current_depth != 1)
    {
        f(current_sum-current_depth, current_depth+1, target_depth);
    }

实现这一点。