剑指offer 34.二叉树中和为某一值的路径
题目描述
解题思路
注意和 leetcode 46. 全排列
、leetcode 78. 子集
、leetcode 77. 组合
回溯的区别,二者的选择列表是一样的,均为所有的孩子节点,主要区别在于路径的记录方式,本题是记录根节点,后者是记录孩子节点。
-
上述的三道回溯题,每到一个节点面临多个选择时,如果做出其中一个选择,则路径中添加的是孩子节点的这个选择。因为根节点为空,初始是从根节点的孩子节点做选择。
所以做选择和撤销选择的操作是在 for 循环里面,即每访问完一个孩子都需要撤销一次选择。这样遍历完后,唯独会忽略根节点的访问。 -
而本题(包括其他的二叉树、图,以及 dp 的递归思路)做选择时,路径中添加的是当前正在做选择的节点。
所以做选择和撤销选择的操作是在 for 循环外面,即只需要访问完所有孩子后,撤销一次根节点的选择。这样遍历完后,会访问完整个树(包括根节点)。
完整代码:
class Solution {
public List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
if (root == null) return res;
LinkedList<Integer> track = new LinkedList<>();
backtrack(root, target, track);
return res;
}
//定义:打印出从root节点一直到叶子节点的路径和为target的路径
public void backtrack(TreeNode root, int target, LinkedList<Integer> track) {
//空节点直接返回
if (root == null) return;
// 到达叶节点
if (root.left == null && root.right == null && target == root.val) {
track.add(root.val);
res.add(new LinkedList<>(track));
track.removeLast();
return;
}
track.add(root.val);
//在已将root添加进路径的基础上,分别打印出左右子树的路径
backtrack(root.left, target - root.val, track);
backtrack(root.right, target - root.val, track);
track.removeLast();
}
}