12.路径总和

📃 题目描述

题目链接:路径总和

image-20220519162253210

🔔 解题思路

可以参考一下 二叉树的所有路径 这题;

方法一:递归方法,回溯,重点:每次传入当前数据的总和进去,每次还需要和targetSum进行比较,太过于麻烦,直接用减法!传入targetSum - root->val进去和下一个节点的val进行对比!

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(!root) return false;
        if(!root->left && !root->right) return targetSum == root->val;
        return hasPathSum(root->left,targetSum - root->val) || hasPathSum(root->right,targetSum - root->val);
    }
};
//为什么不在传入完一条路的所有节点后,判断和是否为0就行?因为避免root = [], targetSum = 0 的情况发生;

方法二:

迭代法,为什么达到和递归函数保存状态,需要用到两个栈,一个保存节点,另一个保存节点所对应的sum值;

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        stack<TreeNode*> treeSt;//保存树遍历的节点;
        stack<int> pathSum;//保存节点对应的总和值;
        if (root == nullptr) return false;
        treeSt.push(root);
        pathSum.push(root->val);
        
        while (!treeSt.empty()) {
            TreeNode *cur = treeSt.top();
            treeSt.pop();
            int sum = pathSum.top();
            pathSum.pop();

            if (!cur->left && !cur->right && sum == targetSum) return true; //叶子节点判断

            if (cur->left) {
                treeSt.push(cur->left); //将该节点压进去
                pathSum.push(sum + cur->left->val); //也将该节点对应的总和值压进去,达到递归函数不同点,总和不同的效果;
            } 
            if (cur->right) {
                treeSt.push(cur->right);
                pathSum.push(sum + cur->right->val);
            }
        }
        return false;
    }
};

优化一些的写法:竟然需要节点和节点的值对应上,那么我们就采用pair来将两个值捆绑在一起;

class solution {

public:
    bool haspathsum(treenode* root, int sum) {
        if (root == null) return false;
        // 此时栈里要放的是pair<节点指针,路径数值>
        stack<pair<treenode*, int>> st;
        st.push(pair<treenode*, int>(root, root->val));
        while (!st.empty()) {
            pair<treenode*, int> node = st.top();
            st.pop();
            // 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
            if (!node.first->left && !node.first->right && sum == node.second) return true;

            // 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
            if (node.first->right) {
                st.push(pair<treenode*, int>(node.first->right, node.second + node.first->right->val));
            }

            // 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
            if (node.first->left) {
                st.push(pair<treenode*, int>(node.first->left, node.second + node.first->left->val));
            }
        }
        return false;
    }
};

💥 复杂度分析

  • 时间复杂度:o(n);
  • 空间复杂度:O(n);

加餐题

题目:路径总和Ⅱ

image-20220519173351890

🔔 解题思路

方法一:回溯法,这题是要把路径拿出啦,那么回溯发就是很好的解决法子,我们采用res作为全局变量保存最后结果,用全局变量path保存当前节点的路径(空间少) / 或者将path作为变量传入(空间多)

下面给出两种代码

代码一:path作为变量

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        finalSum(root, targetSum, {});
        return res;
    }
    void finalSum(TreeNode* root, int targetSum, vector<int> path) {
        if (!root) return;
        if (!root->left && !root->right && targetSum == root->val) {
            path.emplace_back(root->val);
            res.emplace_back(path); //将答案路径加入
            return;
        }

        path.emplace_back(root->val); //加上该路径再进入下一次递归
        if (root->left) {
            finalSum(root->left, targetSum - root->val, path);
        }
        if (root->right) {
            finalSum(root->right, targetSum - root->val, path);
        }
    }
};

代码二:path作为全局变量,空间更加优化!

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        backTracking(root, targetSum);
        return res;
    }
    //回溯找路径;
    void backTracking(TreeNode* root, int targetSum) {
        if (!root) return;
        if (!root->left && !root->right && targetSum == root->val) {
            path.emplace_back(root->val);
            res.emplace_back(path);
            path.pop_back();//回退
            return;
        }

        path.emplace_back(root->val); //加上该路径
        if (root->left) {
            backTracking(root->left, targetSum - root->val);
        }
        if (root->right) {
            backTracking(root->right, targetSum - root->val);
        }
        path.pop_back();//回退
    }
};

时间空间复杂度都和上一题一样;

posted @ 2022-05-19 17:05  D-booker  阅读(72)  评论(0编辑  收藏  举报