23 二叉树中和为某一值的路径 + 回溯法深入总结

题目描述

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路:原来的我是将借口定义为tmp传值的形式,这样多次拷贝数组效率不高,所以改成传引用的形式。

到达二叉树叶子节点的时候,值减为0,那么这条路径就是我们需要的结果。如果到了叶子节点不满足要求,那么下次是空节点,直接返回了。

回溯法的理解:因为想整个递归过程只使用一个tmp数组存储所有的符合条件的路径结果,所以需要使用回溯法,在进行下次递归之前,需要将状态返回到上一步。

看下面第一种思路:

这里遇到叶子节点会有return,这时应该回溯,还有就是中间的左右节点需要回溯,想一下整个递归的过程,首先一直-> left,到达叶子节点后开始回溯,pop_back一个,转向right节点,然后就是中间部分的回溯,对应最后一行的pop_back。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    void helper(vector<vector<int> > &result,vector<int> &tmp,TreeNode* root,int expectNumber){
        if(root == nullptr){
            return;
        }
        expectNumber = expectNumber - root->val;
        tmp.push_back(root -> val);
        if(root -> left == nullptr && root -> right == nullptr){//必须叶子节点才返回
            if(expectNumber == 0){
                result.push_back(tmp);
                tmp.pop_back();
                return;
                }
           else{
                tmp.pop_back();
                return;
            }
        }        

        helper(result,tmp,root -> left,expectNumber);
        helper(result,tmp,root -> right,expectNumber);
        tmp.pop_back();

    }
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        vector<vector<int> > result;
        vector<int> tmp;
        if(root == nullptr){
            return result;
        }
        helper(result,tmp,root,expectNumber);
        return result;
    }
};

其实就是每次return要修改一个共有的东西,push_back了,下次递归之前就必须pop_back.这里就因为有return要终止程序了,而前面有一个push_back的操作,所有后面需要pop_back。

可以这么修改:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    void helper(vector<vector<int> > &result,vector<int> &tmp,TreeNode* root,int expectNumber){
        if(root == nullptr){
            return;
        }
        expectNumber = expectNumber - root->val;
        tmp.push_back(root -> val);
        if(expectNumber == 0 && root -> left == nullptr && root -> right == nullptr){//必须叶子节点才返回
            result.push_back(tmp);
        }        

        helper(result,tmp,root -> left,expectNumber);
        helper(result,tmp,root -> right,expectNumber);
        tmp.pop_back();

    }
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        vector<vector<int> > result;
        vector<int> tmp;
        if(root == nullptr){
            return result;
        }
        helper(result,tmp,root,expectNumber);
        return result;
    }
};

可以联想其他的回溯法的题目,比如permtation,subsets这些问题都可以

下面一个程序是牛客上的某个答案,为什么没有明显的递归基也可以呢?

因为左右节点有判断是否为空,如果都为空那么整个程序就会顺序执行完毕,整个程序就终止了,这也是一种递归基。

class Solution {
    vector<vector<int> >allRes;
    vector<int> tmp;
    void dfsFind(TreeNode * node , int left){
        tmp.push_back(node->val);
        if(left-node->val == 0 && !node->left && !node->right)
            allRes.push_back(tmp);
        else {
            if(node->left) dfsFind(node->left, left-node->val);
            if(node->right) dfsFind(node->right, left-node->val);
        }
        tmp.pop_back(); 
    }
public:
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root) dfsFind(root, expectNumber);
        return allRes;
    }
};
时间: 2024-10-28 20:10:13

23 二叉树中和为某一值的路径 + 回溯法深入总结的相关文章

23.二叉树中和为某一值的路径

二叉树中和为某一值的路径 参与人数:2929时间限制:1秒空间限制:32768K 算法知识视频讲解 题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 牛客网不给测试用例让我感到很迷惑啊..再次提醒自己,vector是否为空用vector.empty()判断! // 24.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <v

打印二叉树中和为某一值的路径

输入一个二叉树,查找该树的所有路径(从根结点到叶结点的通路),并返回和(路径上所有结点值的和)为某一指定值的路径. 1 /////////////二叉树中和为某一值的路径///////////////////// 2 void FindPath(BinaryTreeNode* pRoot ,int expectedSum ,vector<int>& path ,int currentSum) 3 { 4 if (pRoot == NULL) 5 { 6 return; 7 } 8 cu

二叉树中和为某一值的路径-剑指Offer

二叉树中和为某一值的路径 题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 思路 用栈来存储二叉树的路径,遍历到叶子结点就判断是否总和为target,是的话打印,若不是叶子结点,那继续遍历左右子树 注意:打印完后返回父结点时要弹出栈顶的叶子结点,并且总和减去该值 注意:打印路径时要遍历栈 代码 import java.util.ArrayList; import java.util.Stack;

LeetCode | 面试题34. 二叉树中和为某一值的路径【剑指Offer】【Python】

LeetCode 面试题34. 二叉树中和为某一值的路径[剑指Offer][Medium][Python][回溯] 问题 力扣 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径. 示例: 给定如下二叉树,以及目标和 sum = 22, 5 / 4 8 / / 11 13 4 / \ / 7 2 5 1 返回: [ [5,4,11,2], [5,8,4,5] ] 提示: 节点总数 <= 10000 注意:本题与主站 1

25 - 二叉树中和为某一值的路径

题目描述:http://ac.jobdu.com/problem.php?pid=1368 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 解析: 需要找出从根节点到叶节点的路径和等于target,可以想到用深度搜索(前序遍历)方式,当访问某节点时,将该节点添加到路径上,如果该节点是叶节点且恰好等于target,则找到了路径:反之,继续向它的左右子树遍历.当含有该节点的路径不能满足条件时,在返回到父节点

24、二叉树中和为某一值的路径

一.题目 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 二.解法 1 public class Solution { 2 //存储所有的路径 3 private ArrayList<ArrayList<Integer>> listall = new ArrayList<ArrayList<Integer>>(); 4 //存储一条路径 5 private Arra

题目1368:二叉树中和为某一值的路径

题目描述: 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 输入: 每个测试案例包括n+1行: 第一行为2个整数n,k(1<=n<=10000),n表示结点的个数,k表示要求的路径和,结点编号从1到n. 接下来有n行.这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值,leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号

【剑指offer】十七,二叉树中和为某一值的路径

题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 分析:队树的节点值得求和之类的操作大部分都是基于树的遍历操作的,只要对树的遍历操作稍作变形,基本都能解决问题(个人观点).我们知道只有树的先序遍历是首先访问根节点的,此题的关键在于如何把树遍历过程中的节点保存下来,把满足条件的路径加入到结果中,不满足条件的路径节点如何进行重新的搜索.当用前序遍历的方式访问到某一节点时,我们把该节点添加到路径上,并

九度oj 题目1368:二叉树中和为某一值的路径

题目描述: 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 输入: 每个测试案例包括n+1行: 第一行为2个整数n,k(1<=n<=10000),n表示结点的个数,k表示要求的路径和,结点编号从1到n. 接下来有n行.这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值,leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号