給你二元樹的根節點 root 和一個整數目標和 targetSum ,找出所有 從根節點到葉子節點 路徑總和等於給定目標和的路徑。
葉子節點 是指沒有子節點的節點。
範例 1:
輸入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
輸出:[[5,4,11,2],[5,8,4,5]]
範例 2:
輸入:root = [1,2,3], targetSum = 5
輸出:[]
範例 3:
輸入:root = [1,2], targetSum = 0
輸出:[]
提示:
樹中節點總數在範圍 [0, 5000] 內
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
作者:Krahets
連結:https://leetcode.cn/leetbook/read/illustration-of-algorithm/5dy6pt/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
首先能夠想到的是用二元樹遞迴的方式來查詢路徑,每次遞迴都需要修改target
的值,在這種做法中有一個問題:如何設定返回值,從而返回路徑列表,且在程式中如何修改路徑列表?
在官方題解中,在類的定義中適用result
、path
兩個公共變數
,可以讓不同的函數均基於這塊公共區域加以修改。
遍歷使用的是先序遍歷。
path
路徑中;需要注意的是,由於list.add()
使用的是淺拷貝,如果每次將path
新增到結果列表中使用的是result.add(path)
,這樣寫忽略了list.add()
是進行淺拷貝的,即每個路徑結果path
都指向同一個記憶體地址,後續在此記憶體地址上的操作將會改變前期的結果。最終出現[[x,y,z][x,y,z][x,y,z]]
三個子列表相同的情況。因此,每次寫入result
列表應該新建一個path物件。
//LinkedList
LinkedList<E> listname=new LinkedList<E>();//初始化
LinkedList<E> listname=new LinkedList<E>(oldlist);//將oldlist的元素複製一份給listname,且是深拷貝
LinkedList.add(elment);//在連結串列尾部新增元素
LinkedList.removeFirst();//取出連結串列頭部元素
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
// 考慮迭代,左右子樹再找某個目標值的路徑。
class Solution {
LinkedList<List<Integer>> result=new LinkedList<List<Integer>>();
LinkedList<Integer> path=new LinkedList<Integer>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
recur(root,target);
return result;
}
void recur(TreeNode root, int target) {
if(root!=null){
path.add(root.val);
target-=root.val;
if(target==0&&root.left==null&&root.right==null){//遍歷到葉節點且目標值正好等於路徑之和
LinkedList<Integer> path_temp=new LinkedList<Integer>(path);
result.add(path_temp);
}
recur(root.left,target);
recur(root.right,target);
path.removeLast();//回退時將當前元素出棧
}
}
}