24 二叉树的路径和(Binary Tree Path Sum)

1 题目

题目:二叉树的路径和(Binary Tree Path Sum)
描述:给定一个二叉树,找出所有路径中各节点相加总和等于给定 目标值 的路径。一个有效的路径,指的是从根节点到叶节点的路径。

lintcode题号——376,难度——easy

样例1:

输入:{1,2,4,2,3},5
输出: [[1, 2, 2],[1, 4]]
说明:
这棵树如下图所示:
	     1
	    / \
	   2   4
	  / \
	 2   3
对于目标总和为5,很显然1 + 2 + 2 = 1 + 4 = 5

样例2:

输入:{1,2,4,2,3},3
输出: []
说明:
这棵树如下图所示:
	     1
	    / \
	   2   4
	  / \
	 2   3
注意到题目要求我们寻找从根节点到叶子节点的路径。
1 + 2 + 2 = 5, 1 + 2 + 3 = 6, 1 + 4 = 5 
这里没有合法的路径满足和等于3。

2 解决方案

2.1 思路

  使用分治法,获取左右子树满足值为目标值-当前节点值的所有路径,然后在每个路径前拼接上当前节点即可组成答案。
  使用遍历法,递归过程中走到每个叶子节点都判断下路径和是否为目标值,相等的话将路径加入答案集合即可。

2.2 时间复杂度

  分治法和遍历法都需要完整遍历整棵树,算法的时间复杂度为O(n)。

2.3 空间复杂度

  算法的空间复杂度为O(1)。

3 源码

3.1 分治法

细节:

  1. 对叶子结点要特殊处理,否则会导致返回空。
  2. 在vector头部插入可以使用insert,合并两个vector也可以使用insert。

C++版本:

/**
* Definition of TreeNode:
* class TreeNode {
* public:
*     int val;
*     TreeNode *left, *right;
*     TreeNode(int val) {
*         this->val = val;
*         this->left = this->right = NULL;
*     }
* }
*/
/**
* @param root: the root of binary tree
* @param target: An integer
* @return: all valid paths
*          we will sort your return value in output
*/
vector<vector<int>> binaryTreePathSum(TreeNode *root, int target) {
    // write your code here
    vector<vector<int>> results;
    if (root == nullptr)
    {
        return results;
    }

    // 处理叶子节点
    if (root->left == nullptr && root->right == nullptr && target == root->val)
    {
        vector<int> temp;
        temp.push_back(root->val);
        results.push_back(temp);
        return results;
    }

    vector<vector<int>> leftResults = binaryTreePathSum(root->left, target - root->val);
    vector<vector<int>> rightResults = binaryTreePathSum(root->right, target - root->val);

    // 将当前节点值插入左右结果的头部
    for (int i = 0; i < leftResults.size(); i++)
    {
        leftResults.at(i).insert(leftResults.at(i).begin(), root->val);
    }
    for (int i = 0; i < rightResults.size(); i++)
    {
        rightResults.at(i).insert(rightResults.at(i).begin(), root->val);
    }
    // 合并左右结果
    results.insert(results.end(), leftResults.begin(), leftResults.end());
    results.insert(results.end(), rightResults.begin(), rightResults.end());

    return results;
}

3.2 遍历法

细节:

  1. 这题使用遍历法,代码稍复杂,对子树遍历时候需要有回溯操作。
  2. 只有左右子树存在的时候才进行递归。

回溯和节点压入并不成对出现,因为节点无论何时都需压入,但子树可能没有,导致不需要回溯。

C++版本:

/**
* Definition of TreeNode:
* class TreeNode {
* public:
*     int val;
*     TreeNode *left, *right;
*     TreeNode(int val) {
*         this->val = val;
*         this->left = this->right = NULL;
*     }
* }
*/
/**
* @param root: the root of binary tree
* @param target: An integer
* @return: all valid paths
*          we will sort your return value in output
*/
vector<vector<int>> binaryTreePathSum(TreeNode * root, int target) {
    // write your code here
    vector<vector<int>> results;
    if (root == NULL)
    {
        return results;
    }
    
    vector<int> path;
    traverse(root, target, path, results);
    return results;
    }

void traverse(TreeNode * root, int remainTarget, vector<int> &path, vector<vector<int>> &results)
{
    if (root == NULL)
    {
        return;
    }

    path.push_back(root->val);

    // 处理叶子节点
    if (root->left == NULL && root->right == NULL && remainTarget == root->val)
    {
        results.push_back(path);
        return;
    }

    // 进入左子树,需要回溯
    if (root->left != NULL)
    {
        traverse(root->left, remainTarget - root->val, path, results);
        path.pop_back(); // 回溯
    }
    // 进入右子树,需要回溯
    if (root->right != NULL)
    {
        traverse(root->right, remainTarget - root->val, path, results);
        path.pop_back(); // 回溯
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值