題目來源:力扣
題目描述:
輸入一棵二叉樹和一個整數,打印出二叉樹中節點值的和爲輸入整數的所有路徑。從樹的根節點開始往下一直到葉節點所經過的節點形成一條路徑。
審題:
該題目爲樹搜索中的路徑和問題.本題的複雜之處在於不單單是搜索符合要求的路徑數量,而且是要打印出路徑.本題的簡單之處則在於對路徑的定義:路徑從根節點開始,且結束於葉節點.
考慮我們該如何打印出節點的路徑呢?對於這道題,我一開始的設計是構建鍵值對,紀錄每一節點的父節點,這樣當我們搜索到符合要求的葉節點時,我們可沿葉節點的父節點一路向上回溯,直到根節點.關於該方法的實現後文會給出java代碼.後來我看了其他人的題解,發現在此處使用鍵值對有點繁瑣,增加了額外的空間複雜度與時間複雜度.考慮當前函數的遞歸調用自然而然的維護了從根節點到當前節點的一條路徑.因此我們可在自上而下遍歷節點的過程中,記錄當前路徑中的節點值,如果到達符合要求的葉節點處,我們將該條路徑上的值複製,然後添加到總路徑中即可.我們也給出這種算法的java代碼.
java算法
方法一:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//使用鍵值對紀錄當前節點的父節點
Map<TreeNode, TreeNode> map = new HashMap<>();
Stack<TreeNode> stack = new Stack<>();
private void _pathSum(TreeNode x, int sum, int currentVal, List<List<Integer>> paths){
if(x == null)
return;
if(x.val + currentVal == sum && x.left == null && x.right == null){
//如果當前找到一條路徑,則回溯這條路徑
TreeNode cur = x;
while(cur != null){
stack.push(cur);
cur = map.get(cur);
}
List<Integer> path = new LinkedList<>();
while(!stack.isEmpty())
path.add(stack.pop().val);
paths.add(path);
}
if(x.left != null){
map.put(x.left, x);
_pathSum(x.left, sum, currentVal+x.val, paths);
}
if(x.right != null){
map.put(x.right, x);
_pathSum(x.right, sum, currentVal+x.val, paths);
}
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
map.put(root, null);
List<List<Integer>> paths = new LinkedList<>();
_pathSum(root, sum, 0, paths);
return paths;
}
}
方法二:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//使用一個列表來保存當前函數遞歸調用棧上的節點值
private void _pathSum(TreeNode x, int sum, List<Integer> currentPath, List<List<Integer>> paths){
if(x == null)
return;
currentPath.add(x.val);
sum -= x.val;
if(sum == 0 && x.left == null && x.right == null){//如果當前找到一條路徑
List<Integer> path = new ArrayList(currentPath);
paths.add(path);
}
_pathSum(x.left, sum, currentPath, paths);
_pathSum(x.right, sum, currentPath, paths);
currentPath.remove(currentPath.size()-1); //移除最後一個元素,退棧;
sum += x.val;
return;
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> paths = new LinkedList<>();
List<Integer> currentPath = new LinkedList<>();
_pathSum(root, sum, currentPath, paths);
return paths;
}
}