輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的全部路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所通過的結點造成一條路徑。java
設二叉樹爲{10,5,12,4,7},和爲22,則打印出兩條路徑,第一條路徑爲10,12,第二條路徑爲10,5,7。使用前序遍歷的方法訪問到某一節點時,咱們把該節點添加到路徑上,並累加該節點的值。若是該節點爲葉子節點(即該節點的左右子節點均爲null)而且路徑中節點值的和恰好等於輸入的整數,則當前的路徑符合要求,咱們把它打印出來。若是當前節點不是葉結點,則繼續訪問它的子節點。當前訪問結束後,遞歸函數將自動回到它的父節點。所以咱們在函數退出以前要在路徑上刪除當前節點並減去當前節點的值,以確保返回父節點的路徑恰好是從根節點到父節點的路徑。不難看出保存路徑的數據結構其實是一個棧,由於路徑要與遞歸調用狀態一致,而遞歸調用的本質就是一個壓棧和出棧的過程。node
package com.swordOffer.pathInTree16; import java.util.ArrayList; /** * Created by Feng on 2017/5/14. * 輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的全部路徑。 * 路徑定義爲從樹的根結點開始往下一直到葉結點所通過的結點造成一條路徑。 */
public class PathInTree { //存儲節點的值
static ArrayList<Integer> list = new ArrayList<Integer>(); //存儲路徑
static ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>(); public static void main(String[] args) { TreeNode node1 = new TreeNode(10); TreeNode node2 = new TreeNode(5); TreeNode node3 = new TreeNode(12); TreeNode node4 = new TreeNode(4); TreeNode node5 = new TreeNode(7); node1.left = node2; node1.right = node3; node2.left = node4; node2.right = node5; ArrayList<ArrayList<Integer>> result = findPath(node1, 22); for (ArrayList<Integer> list : result) { for (Integer integer : list) { System.out.print(integer + " "); } } } public static ArrayList<ArrayList<Integer>> findPath(TreeNode root, int target) { if (root == null) { return listAll; } //添加根節點
list.add(root.val); //當前目標的值爲減去根節點後的值
target -= root.val; //若是節點爲葉子節點且路徑的值和目標的值相等
if (target == 0 && root.left == null && root.right == null) { listAll.add(new ArrayList<>(list)); } //採用遞歸,回到父節點
findPath(root.left, target); findPath(root.right, target); //刪除當前節點
list.remove(list.size() - 1); return listAll; } } class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } }