检查二叉树的路径是否等于给定的总和

时间:2017-10-31 19:28:10

标签: c binary-tree computer-science

我在解决此问题的解决方案时遇到了问题:

"给定一个二叉树(每个节点都有一个int值)和一个sum,如果树的路径等于给定的总和(从节点到叶子,则返回1)必须是根),否则返回0"。

我做了类似的问题,路径必须从根开始。 但是在这里,问题表明路径可以从任何地方开始,只要它以叶子结束......

尝试在线搜索解决方案,但我发现一些只能使用缓冲区。

有没有可能的解决方案,没有缓冲区?

提前致谢!

(首选C,C ++语法甚至伪代码^。^``)

这是我的第一次尝试:

int hasPathSum(Tree tr, int sum){
return hasPathSumRec(tr.root, sum, 0);
}


int hasPathSumRec(TNode* node, int sum, int current){

int num1, num2;
current += node->data;
if (current > sum)
    current = 0;

if (node->left == NULL && node->right == NULL){
    if (current == sum)
        return 1;
    return 0;
}
else if (node->left == NULL){
    return hasPathSumRec(node->right, sum, current);

}
else if (node->right == NULL){
    return hasPathSumRec(node->left, sum, current);
}
else{
    num1=hasPathSumRec(node->left, sum, current);
    num2=hasPathSumRec(node->right, sum, current);

    if (num1 > 0 || num2 > 0)
        return 1;
    else
        return 0;
}
}

这是第二个:(但它没有通过所有节点,所以它不好......)

int hasPathSum(Tree tr, int sum){
return hasPathSumRec(tr.root, sum, 0);
}

int hasPathSumRec(TNode* node, int sum, int current){
int num, num1, num2;


num = node->data;
current = num + current;

if (current > sum)
    current = num;


if (node->left == NULL && node->right == NULL){
    if (node->data == sum || current == sum)
        return 1;
    else
        return 0;
}
else if (node->left == NULL){
    num2 = node->right->data;
    if (current + num2 > sum)
        return hasPathSumRec(node->right, sum, num);

    else
        return hasPathSumRec(node->right, sum, current);

}
else if (node->right == NULL){
    num1 = node->left->data;
    if (current + num1 > sum)
        return hasPathSumRec(node->left, sum, num);
    else
        return hasPathSumRec(node->left, sum, current);

}
else{
    num1 = node->left->data;
    num2 = node->right->data;
    /LEFT SIDE--------------------------------------------------/
    if (current + num1 > sum)
        num2 = hasPathSumRec(node->left, sum, num);
    else
        num2 = hasPathSumRec(node->left, sum, current);
    /RIGHT SIDE--------------------------------------------------/
    if (current + num2 > sum)
        num1 = hasPathSumRec(node->right, sum,num);
    else
        num1 = hasPathSumRec(node->right, sum, current);


    if (num1 > 0 || num2 > 0)
        return 1;
    else
        return 0;
}

2 个答案:

答案 0 :(得分:1)

正如您已经提到的,您将树值的总和计算为其子树总和加上根值的总和。很明显,只要你能计算出这棵树的总和,就可以计算出所有子树的总和。因此,唯一要做的就是添加一个检查,如果总和等于所需的并将其返回。在这里你可以找到这个想法的实现和一个Minimal, Complete, and Verifiable example,你应该首先提供它,这样可以节省人们(我)写一个的努力。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct _TNode {
    int data;
    struct _TNode *left, *right;
} TNode;

typedef struct {
    TNode *root;
} Tree;

typedef struct {
    int sum;
    bool found;
} hasPathSumRec_t;

hasPathSumRec_t hasPathSumRec(TNode* node, int sum)
{
    hasPathSumRec_t ret = { 0, false };
    if (!node)
        return ret;

    hasPathSumRec_t ret_left = hasPathSumRec(node->left, sum);
    hasPathSumRec_t ret_right = hasPathSumRec(node->right, sum);

    ret.sum = ret_left.sum + ret_right.sum + node->data;
    ret.found = ret_left.found || ret_right.found || ret.sum == sum;
    return ret;
}

int hasPathSum(Tree tr, int sum) {
    return hasPathSumRec(tr.root, sum).found;
}

int main(void)
{
    /*
    1 / 2 / 3 / *
      |   |   \ *
      |   \ 5 / * 
      |       \ *
      \ 4 / 6 / 7 / *
          |   |   \ *
          |   \ *
          \ 8 / *
              \ 9 / *
                  \ *
    */

    TNode n[] = {
        { 1, n + 4 - 1, n + 2 - 1 },
        { 2, n + 5 - 1, n + 3 - 1 },
        { 3, NULL, NULL },
        { 4, n + 8 - 1, n + 6 - 1 },
        { 5, NULL, NULL },
        { 6, NULL, n + 7 - 1 },
        { 7, NULL, NULL },
        { 8, n + 9 - 1, NULL },
        { 9, NULL, NULL },
    };

    Tree t = { n };

    int tests[] = { 8, 9, 10, 12, 13, 17 };
    size_t ntests = sizeof tests / sizeof *tests;
    for (size_t i = 0; i < ntests; ++i)
        printf("%i - %i\n", tests[i], hasPathSum(t, tests[i]));
}

如果发现或超过金额,进一步的改进可以允许提前退出。

答案 1 :(得分:0)

  
    

我做了类似的问题,路径必须从根开始。但是在这里,问题表明路径可以从任何地方开始,只要它以叶子结束。有没有可能的解决方案,没有缓冲区?

  

如果您已经有一个带有根节点的解决方案,那么它不再需要一次递归。

假设您的基于根节点的解决方案名为IsPathHasSum(root)。如果从根到叶的任何路径上的节点总数与给定的总和匹配,则返回1。此函数应仅查找从根到叶的路径,而不是从任意节点开始的中间路径。

现在涵盖所有节点,

-> Start with IsPathHasSum(root), if return value = 1, program terminates
-> If not, invoke IsPathHasSum(root->left). This ignore the root and right tree. 
-> If not, invoke IsPathHasSum(root->right). This ignores root and left tree

这可以递归调用,从树的每个节点开始直到叶子。如果在任何时候,返回值为1,程序终止。由于您的要求是没有任何缓冲区,因此需要一次又一次地在相同路径上重新遍历。