描述
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
1 2 3 4 5 6 7 8 9 10 root = [10 ,5 ,-3 ,3 ,2 ,null,11 ,3 ,-2 ,null,1 ], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1
返回 3。和等于 8 的路径有:
5 -> 3
5 -> 2 -> 1
-3 -> 11
来源:力扣(LeetCode)
链接:437. Path Sum III
解题思路
总体的思路还是要递归,那么怎么递归呢?这是个问题。
一种比较简洁的思路是使用两个递归函数,其中一个递归函数sumUp是以当前节点为起点,其中参数有当前节点的指针* node,记录之前路径之和的变量pre,给定的路径和sum,返回和为sum的路径个数。
sumUp函数采用了前序遍历,对于每个遍历到的节点进行处理,用变量 pre 来记录之前路径之和,然后 cur 为 pre 加上当前节点值,如果 cur 等于 sum,那么返回结果时要加1,然后对当前节点的左右子节点调用递归函数求解。
另外一个递归函数就是原pathSum函数的递归调用,在 pathSum 函数中,我们对当前结点调用 sumUp 函数,加上对左右子结点调用 pathSum 递归函数,三者的返回值相加就是所求,具体代码见解法一。
另外一种仅采用一个递归函数,姑且叫做helper。其中参数有当前节点的指针* node,给定的路径和sum,路径和是否仅包含当前节点的值的标记flag,返回和为sum的路径总个数。
helper函数也是采用了前序遍历,用number表示需要返回的个数,当路径不仅仅包含当前节点及其左右子节点时,将后续递归函数当中的sum用sum减去当前节点的val来代替,即sum - node->val。具体代码见解法二。
然后再提交以后的查看详情里面看到有人用栈进行求解,这边给代码加下注释放在解法三,大家对照着看看。
显然,解法三洋洋洒洒要100多行,而且是在不包括测试代码的情况下,要是说此题简单我是不相信的( ̄▽ ̄)
代码
解法一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int sumUp (struct TreeNode* node, int pre, int sum) { if (!node) return 0 ; int cur = pre + node->val; return (cur == sum) + sumUp(node->left, cur, sum) + sumUp(node->right, cur, sum); } int pathSum (struct TreeNode* root, int sum) { if (!root) return 0 ; return sumUp(root, 0 , sum) + pathSum(root->left, sum) + pathSum(root->right, sum); }
解法二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int helper (struct TreeNode* node, int sum, int flag) { if (!node) return 0 ; else { int number = 0 ; if (node->val == sum){ number += 1 ; } if (flag == 1 ){ number += helper(node->left, sum, 1 ); number += helper(node->right, sum, 1 ); } number += helper(node->left, sum - node->val, 0 ); number += helper(node->right, sum - node->val, 0 ); return number; } } int pathSum (struct TreeNode* root, int sum) { return helper(root, sum, 1 ); }
解法三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 #define MAX_CNT 1000 typedef struct { int target; int total; int cnt; struct TreeNode * data [MAX_CNT + 1]; }Stack; void StackInit (Stack *st, int target, int total, int cnt) { st->cnt = cnt; st->target = target; st->total = total; } void StackPush (Stack *st, struct TreeNode *node) { if ((st->cnt < MAX_CNT) && (node != NULL )) { st->data[st->cnt++] = node; } } struct TreeNode* StackPop (Stack *st) { struct TreeNode *node = NULL ; if (st->cnt > 0 ) { node = st->data[st->cnt--]; } return node; } int CaclSumCorrect (Stack *st) { int i = st->cnt; int sum = 0 ; int result = 0 ; for (; i > 0 ; --i) { sum += st->data[i - 1 ]->val; if (sum == st->target) { result += 1 ; } } return result; } void VisitTree (struct TreeNode* root, Stack *st) { int result; if (root != NULL ) { StackPush(st, root); st->total += CaclSumCorrect(st); if (root->left != NULL ) { VisitTree(root->left, st); } if (root->right != NULL ) { VisitTree(root->right, st); } StackPop(st); } } int pathSum (struct TreeNode* root, int sum) { Stack st; StackInit(&st, sum, 0 , 0 ); VisitTree(root, &st); return st.total; }
参考