【LeetCode】【回溯法】剑指 Offer 34. 二叉树中和为某一值的路径 思路解析和代码

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

题目链接

个人思路

题意

在这里插入图片描述

思路

此题的子集属于排列树

  • 递归参数:当前的根节点root,目标sum,当前累加数字cur
  • 递归出口:当根节点为空时,直接return
  • 递归体:将root中的数据加入temp,进行累加,判断是否满足sum,递归访问左右子树(撤销选择的细节问题见下方)
    • 剪枝判断:如果cur == sum 且当前节点为叶子节点,则进行存储输出(return的细节问题见下方)

注意

  • 为什么要撤销选择?撤销操作其实是用vector模拟栈: 如果我们遍历到一条路径的叶节点了,然后需要切换到下一条路径的叶节点(比如题目示例中,我们遍历完了 5-4-11-7,现在要从 7 切换到 右边的 2),我们需要先从 temp 中把 7 pop_back。这样才能保证切换了之后,temp里的值会是:5,4,11,2;而不是:5,4,11,7,2。
  • 为什么不需要撤销cur? 因为我们这里用的是递归,也就是当递归到头的时候会回溯。所以sum和temp不同,temp是只有一个,每次递归都是直接在操作(改变)temp里的值;但是sum是每次递归都有自己的sum,所以递归到头,回溯到上一级,sum指的是上一级的sum。故不需要对sum做操作。可能有一点绕,但是意思其实就是:temp只有一个,sum则是每次递归都有自己的sum
  • 递归出口中return的作用,何时要return,return的注意事项: return可以终止当前这一层的递归,如果在递归出口中使用return,递归出口下方的所有语句将不再执行,包括之后的撤销语句。因此如果写return语句,则在return之前需要先temp.pop_back(),以撤销选择
  • 递归出口中暂存的数据temp何时要清空? :根据题意来定,因为二叉树的回溯时只是需要遍历分叉位置之后的分支,而分叉位置之前的数据不需要清空

个人思路代码

错误代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    vector<vector<int> > vec;
    vector<int> temp;
    void getSum(TreeNode* root, int sum, int cur){
        if(root == NULL){
            if(cur == sum){
                // cout << "****" << endl;
                vec.push_back(temp);
            }
            cout << cur << endl;
            temp.clear();//问题一
            return;//问题二
        }
        temp.push_back(root->val);//问题三
        cur += root->val;
        getSum(root->left, sum, cur);
        getSum(root->right, sum, cur);
        temp.pop_back();
        cur -= root->val;//问题四
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        getSum(root, sum, 0);
        return vec;
    }
};
正确代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int> > vec;
    vector<int> temp;
    void getSum(TreeNode* root, int sum, int cur){
        if(root == NULL)//空节点
            return;
        temp.push_back(root->val);
        cur += root->val;
        if(cur == sum && root->left == NULL && root->right == NULL){//判断是否等于sum,且是否走到了叶子节点
            vec.push_back(temp);
            temp.pop_back();
            return;
        }
        getSum(root->left, sum, cur);
        getSum(root->right, sum, cur);
        temp.pop_back();
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        getSum(root, sum, 0);
        return vec;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值