leetcode 路径总和系列(1,2,3,4)

leetcode 112. 路径总和  easy         

题目描述:

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

解题思路:

方法1:简单的dfs即可

方法2:迭代。

用先序遍历,但是遍历到的每个节点它的左右子结点都需要加上其父结点值,再压入栈中。这样当遍历到叶结点时,如果和sum相等了,那么就说明一定有一条从root过来的路径。

代码:

// dfs
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(root==nullptr)
            return false;
        
        return dfs(root,0,sum);
    }
    
    
    bool dfs(TreeNode* root,int cur,int target){
        if(root==nullptr)
            return false;
        
        cur += root->val;

        // 是叶节点且路径总和等于target
        if(root->left==nullptr && root->right==nullptr && cur==target)
            return true;

        return dfs(root->left,cur,target) || dfs(root->right,cur,target);
        
        
    }
    
};


// 迭代 先序遍历
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (!root) return false;
        stack st{{root}};
        while (!st.empty()) {
            TreeNode *t = st.top(); st.pop();
            if (!t->left && !t->right) {
                if (t->val == sum) return true;
            }
            if (t->right) {
                t->right->val += t->val;
                st.push(t->right);
            }
            if (t->left) {
                t->left->val += t->val;
                st.push(t->left);
            }
        }
        return false;
    }
};

 

leetcode 113. 路径总和 II   medium          

题目描述:

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

解题思路:

dfs

代码:

class Solution {
public:
    vector> pathSum(TreeNode* root, int sum) {
        if(root==nullptr)
            return {};
        
        vector> res;
        vector out;
        dfs(root,0,sum,res,out);
        return res;
    }
    
    
    void dfs(TreeNode *root, int cur,int target,vector> &res,vector &out){
        if(root==nullptr)
            return;
        
        cur += root->val;
        out.push_back(root->val);
        if(!root->left && !root->right && cur==target){
            res.push_back(out);
        }
        
        dfs(root->left,cur,target,res,out);
        dfs(root->right,cur,target,res,out);
        out.pop_back();
        
        
    }
    
};

leetcode 437. 路径总和 III  easy           

题目描述:

给定一个二叉树,它的每个结点都存放着一个整数值。

找出路径和等于给定数值的路径总数。

路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

解题思路:

方法1: 先序遍历每个节点,求以每个节点为根(也就是起点)的符合条件的路径 (第n层节点会被遍历n次)

方法2:还是先序遍历每个节点,但这次计算以每个节点为终点的,所有符合路径的值,而该路径上的前缀和用哈希表来存

(每个节点只需要遍历1次)

代码:

//先序遍历每个节点,但这次计算以每个节点为终点的,所有符合路径的值
class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if(!root)
            return 0;
        int res=0;
        
        unordered_map pre;
        pre[0]=1; // 为了下面 res += pre【cur-target】的统一性
        dfs(root,0,sum,pre,res);
        
        return res;
    }
    

    // 依旧先序遍历每个节点,但是这次遍历到每个节点的时候,求以该节点为终点的,所有符合路径的值
    
    // 而前缀和通过pre来存储,相当于用空间换了时间
    void dfs(TreeNode* root,int cur,int target,
             unordered_map & pre,int &res){
        if(!root)
            return;
        cur += root->val;
        res += pre[cur-target]; // res +=  (pre.count(cur-target)?pre[cur-target]:0);
        
        ++pre[cur];
        dfs(root->left,cur,target,pre,res);
        dfs(root->right,cur,target,pre,res);
        --pre[cur];
        /*
        if(pre[cur]==0)
            pre.erase(cur);
        */
    }
    
};






// 一开始的代码
class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if(!root)
            return 0;
        int res=0;
        
        helper(root,sum,res);
        return res;
    }
    
    //先序遍历每个节点,dfs求 以每个节点为根的符合要求的路径
    void helper(TreeNode* root,int target,int &res){
        if(!root)
            return;
        dfs(root,0,target,res);
        
        helper(root->left,target,res);
        helper(root->right,target,res);
        
        
    }
    
    
    void dfs(TreeNode* root,int cur,int target,int &res){
        if(!root)
            return;
        cur += root->val;
        
        if(cur==target)
            ++res;
        
        dfs(root->left,cur,target,res);
        dfs(root->right,cur,target,res);

        
    }
    
};

leetcode 666. 路径和 IV   medium          

题目描述:

对于一棵深度小于 5 的树,可以用一组三位十进制整数来表示。

对于每个整数:

百位上的数字表示这个节点的深度 D,1 <= D <= 4。
十位上的数字表示这个节点在当前层所在的位置 P, 1 <= P <= 8。位置编号与一棵满二叉树的位置编号相同。
个位上的数字表示这个节点的权值 V,0 <= V <= 9。
给定一个包含三位整数的升序数组,表示一棵深度小于 5 的二叉树,请你返回从根到所有叶子结点的路径之和。

样例 1:

输入: [113, 215, 221]
输出: 12
解释: 
这棵树形状如下:
    3
   / \
  5   1

路径和 = (3 + 5) + (3 + 1) = 12.

解题思路:

虽然给的不是根节点,但是我们可以通过给每个节点编号的方式来找到他对应的左右儿子,具体办法是用一个哈希表保存下标到节点值的映射,而每个节点的下标是按照层序一个满二叉树的方式来建立的,所以下标为k的左右儿子的下标为2k 和 2k+1。

代码:

class Solution {
public:
    int pathSum(vector& nums) {
        if(nums.empty())
            return 0;
        
        // 按照层序满二叉树建立下标
        // 则一个下标为k的左右儿子 下标为2k 和 2k+1
        unordered_map dict;
        for(int i:nums){
            int depth=i/100;
            int p=i%100/10;
            int val= i%10;
            int temp=pow(2,depth-1)-1+p;
            dict[temp]=val;
        }
        
        int res=0;
        dfs(1,0,res,dict);
        return res;
        
    }
    
    void dfs(int index,int cur,int& res,unordered_map &dict){
        // 当前节点不存在
        if(!dict.count(index))
            return;
        
        cur += dict[index];
        if(!dict.count(2*index) && !dict.count(2*index+1)){
            res += cur;
            return;
        }
        
        dfs(2*index,cur,res,dict);
        dfs(2*index+1,cur,res,dict);
        
    }
    
};

你可能感兴趣的:(leetcode,树,回溯)