我在解决此问题的解决方案时遇到了问题:
"给定一个二叉树(每个节点都有一个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;
}
答案 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,程序终止。由于您的要求是没有任何缓冲区,因此需要一次又一次地在相同路径上重新遍历。