題目描述
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
For example:
Given the below binary tree and sum = 22,5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1
return
[
[5,4,11,2],
[5,8,4,5]
]
解題思路
做此題前可以先嚐試path_sum,判斷二叉樹是否存在一條根節點到葉子節點路徑使得數值和等於sum,這裏則是求出所有的這樣的路徑集合。
原先的遞歸關鍵點是對左右兒子節點遞歸,左右有一個返回true,當前函數就返回true,現在我們是計算路徑,所以每個節點都需要對左右子樹遍歷,對於符合條件的路徑加入到結果結合中。
爲了找到一條路徑,我定義了一個SuperNode,可以記錄其前驅,數據結構如下:
public class SuperNode {
int val;
SuperNode pre;//指向前驅節點
public SuperNode(int x)
{
val = x;
pre = null;
}
}
每次經過一個節點,我們都建立一個supernode sn,標記該節點的val,以及其前驅,如果找到一條符合條件的通路,則把這個sn加入到我們的節點結合List中,最後對list遍歷,對其中每個元素sn,進行找前驅的方式,可以得到一條路徑,然後放到路徑集合中。
詳細代碼
//path sum2
public List<List<Integer>> pathSum(TreeNode root, int sum)
{
List<List<Integer>> resultLists = new ArrayList<>();//結果路徑集合
List<SuperNode> superNodes = new ArrayList<>();//supernodes 集合,每個supernode可以生成一條路徑。
if(root == null)
{
return resultLists;
}
findPathSum(root, sum, new SuperNode(root.val), superNodes);
for(SuperNode sn:superNodes)//對supernodes進行遍歷,每個node生成一條路徑
{
List<Integer> lists = new LinkedList<>(); //利用鏈表插入提高效率
while(sn != null)
{
lists.add(0, sn.val);
sn = sn.pre;
}
resultLists.add(lists);
}
return resultLists;
}
public class SuperNode {
int val;
SuperNode pre;//指向前驅節點
public SuperNode(int x)
{
val = x;
pre = null;
}
}
//找到指定路徑 返回null爲沒有 否則可以根據node遍歷得到逆序
public void findPathSum(TreeNode root, int sum, SuperNode sn, List<SuperNode> superNodes) {
if(root == null)
{
//空樹 結束條件之一
return;
}
else
{
if(root.left==null && root.right==null)
{
//葉子節點 left right都爲空
if(sum== root.val)
{
superNodes.add(sn);
return;
}
else
{
return;
}
}
else
{
//非葉子結點
if(root.left != null)
{
SuperNode node = new SuperNode(root.left.val);
node.pre = sn;
findPathSum(root.left, sum-root.val,node, superNodes);
}
if(root.right != null)
{
SuperNode node = new SuperNode(root.right.val);
node.pre = sn;
findPathSum(root.right, sum-root.val,node, superNodes);
}
}
}
}