【问题标题】:Check if a binary tree has a path equal to the given sum检查二叉树的路径是否等于给定的总和
【发布时间】:2017-10-31 19:28:09
【问题描述】:

我在想办法解决这个问题时遇到了问题:

"给定一棵二叉树(每个节点都有一个 int 值)和一个 sum,如果树的路径等于给定 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;
}

【问题讨论】:

  • 你能展示一些你已经尝试过的 C、C++ 甚至是伪代码吗?
  • 添加到原帖
  • @Martin 记得检查答案是否正常,如果是则将其标记为已接受,或者评论为什么不是。

标签: c binary-tree computer-science


【解决方案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]));
}

如果发现或超过总和,进一步的改进可能允许提前退出。

【讨论】:

  • 是的,解决方案有效,还没有对二叉树的返回结构进行递归,所以我什至没有接近这个哈哈,非常感谢!
  • @Martin:只是为了完整性,作为练习,您可以在不返回结构的情况下解决问题。使用指向某个参数的指针并正确管理递归。
【解决方案2】:

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

如果你已经有了根节点的解决方案,那么它不只是需要一个递归。

假设您的基于根节点的解决方案称为 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,则程序终止。由于您的要求是没有任何缓冲区,因此需要一次又一次地在相同路径上重新遍历。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 2015-04-23
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    相关资源
    最近更新 更多