二叉树中和为某一值的路径(二):最直观的想法是,从根节点依次从上向下从左向右直到叶子节点,一条路径一条路径的判断,当到达叶子节点时,如果满足要求则加入结果集,反之不满足要求则弹出叶子节点转向其父节点的下一条路径继续进行判断,如此反复直至所有路径遍历结束即可。整个遍历过程十分容易模拟,那么如何将模拟过程转化为代码呢?首先使用一个变量result记录整个结果集,使用一个变量path记录当前路径,为了方便起见,此处将这两个变量设置为全局变量。首先判断根节点root是否为空,如果为空则直接返回空的result,反之将根节点root和期待值expectNumber传入dfs函数。由于一进入dfs函数就需要将当前节点的值加入当前路径path中,故要保证当前节点不为空,该判断条件在进入dfs之前就进行判断即可,否则如果进入时允许节点为空,那么将节点值加入path就会很麻烦。当当前节点到达叶子节点,即当前节点的左右孩子均为空,且当前节点值等于期待值时,则表示当前路径满足条件,故将当前路径path加入结果集result中并返回即可,反之如果不等于,则直接返回即可。即dfs到达叶子节点即会返回,此时在左右孩子节点不为空的判断中,存在dfs函数被返回,一定要在紧跟着的dfs函数之后弹出叶子节点元素,这样再继续下一个方向的才对,否则答案会出错!
vector<vector<int>> result; //记录所有结果 vector<int> path; //记录当前结果 void dfs(TreeNode* root,int expectNumber) { //一进入递归就加入节点的值 故节点不为空 即在后续递归时判断是否为空 path.push_back(root->val); //如果已经到达叶子结点并且叶子节点的值等于待求解值则加入结果集 if(!root->left&&!root->right&&root->val==expectNumber) { result.push_back(path); return; //返回 } //该条路径不满足则直接返回 if(!root->left&&!root->right&&root->val!=expectNumber) { return; //返回 } //左节点不为空才执行 if(root->left) { //如果左节点不为空 则待求解值等于当前值减去根节点值 dfs(root->left,expectNumber-root->val); //一旦dfs返回 无论是满足条件加入结果返回 还是不满足结果直接返回 必定是到达叶子结点 此时弹出叶子节点即可 注意一定要先弹出再去遍历右边 否则容易出错 path.pop_back(); } //右节点不为空才执行 if(root->right) { //如果右节点不为空 则待求解值等于当前值减去根节点值 dfs(root->right,expectNumber-root->val); //注意 result和path是全局变量! path.pop_back(); } } vector<vector<int>> FindPath(TreeNode* root,int expectNumber) { if(root==nullptr) return result; dfs(root,expectNumber); return result; }
注意:此处我是一遍历到节点就加入该节点的值,那么对应的叶子节点即是期待值减去当前值!