题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
思路1:带有记忆的dfs,典型解法
1、先序遍历树,把节点加入路径
2、若该节点是叶子节点则比较当前路径和是否等于给定值
3、弹出节点,每一轮递归返回到父节点时,当前路径也应该回退一个节点
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root, int expectNumber) {
vector<vector<int>> res; //所有路径
vector<int> arr; //每一条路径
if (root == nullptr || expectNumber <= 0)
return res;
return dfs(root, expectNumber, arr, res);
}
vector<vector<int>> dfs(TreeNode* root, int numdist, vector<int>& arr,vector<vector<int>>& res) {
arr.push_back(root->val);
if (root->val == numdist && root->left==nullptr && root->right==nullptr) { //走到叶子节点,且满足路径和==给定值,就push进res
res.push_back(arr);
}
if (root->left) //root->left!=nullptr,递归左子树
dfs(root->left, numdist-root->val, arr, res);
if (root->right)
dfs(root->right, numdist-root->val, arr, res);
arr.pop_back(); //已到达叶子节点,但路径和!=给定值,就pop掉当前值,返回到上一层
return res;
}
};
思路2:非递归,用栈实现后序遍历
1、进栈时,同时压入值到栈和子数组,并修正路径和
2、出栈时,判断路径和是否满足给定值,且到达叶节点,满足则添加,否则返回上一个节点再操作
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root, int expectNumber) {
vector<vector<int> > res;
vector<int> arr;
stack<TreeNode*> st;
if (root == nullptr || expectNumber <= 0)
return res;
while (root || !st.empty()) //root!=nullptr
{
while (root)
{
st.push(root);
arr.push_back(root->val);
expectNumber -= root->val;
root = root->left ? root->left : root->right; //root->left != nullptr //能左就左,否则向右
}
root = st.top();
if (expectNumber == 0 && root->left == nullptr && root->right == nullptr)
res.push_back(arr);
st.pop();
arr.pop_back();
expectNumber += root->val;
if (!st.empty() && st.top()->left == root) //右子树没遍历就遍历,如果遍历就强迫出栈
root = st.top()->right;
else
root = nullptr; //强迫出栈
}
return res;
}
};