1. 程式人生 > >【劍指offer】面試題34:二叉樹中和為某一值的路徑

【劍指offer】面試題34:二叉樹中和為某一值的路徑

題目:輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,陣列長度大的陣列靠前)

 連結:https://www.nowcoder.com/questionTerminal/b736e784e3e34731af99065031301bca

由於 TreeNode 類中 node 節點沒有指向其父節點的指標,所以需要將訪問過的節點路徑都儲存下來。

當用前序遍歷的方式訪問到某一節點時,我們把該節點新增到路徑上,並累加該節點的值。如果該結點為葉結點並且路徑中結點值的和剛好為輸入的整數,則當前的路徑符合要求,我們把它打印出來。如果當前的結點不是葉結點,則繼續訪問它的子節點。當前結點訪問結束後,遞迴函式將自動回到它的父節點。因此我們在函式退出之前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父節點時路徑剛好是從根節點到父節點的路徑。我們不難看出儲存路徑的資料結構實際上是一個棧,因此路徑要與遞迴呼叫狀態一致,而遞迴呼叫的本質上是一個壓棧和出棧的過程。

package com.zju.offer.tree;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * 輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。
 * 路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。
 * (注意: 在返回值的list中,陣列長度大的陣列靠前)
 */
public class FindPathEqualNum {

	public class TreeNode{
		private int val;
		private TreeNode left = null;
		private TreeNode right = null;
		
		public TreeNode(int val){
			this.val = val;
		}
	}
	// 所有符合條件路徑的集合
	private ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>();
	// 單條路徑節點元素的的集合
	private ArrayList<Integer> list = new ArrayList<Integer>();
	 
	public ArrayList<ArrayList<Integer>> findPath(TreeNode root, int target){
		if(root == null){
			return null;
		}
		list.add(root.val);  // 先將根節點加入路徑集合中
		target -= root.val;
		if(target == 0 && root.left == null && root.right == null){
			// target等於0,並且當前節點是葉子節點,則說明該路徑符合條件
			listAll.add(new ArrayList<Integer>(list));
		}
		findPath(root.left, target);  // 左子樹迭代查詢
		findPath(root.right, target); // 右子樹迭代查詢
		// 如果當前路徑已經到了葉子節點也不符合條件,則退回其父節點
		// 深度遍歷完一條路徑後要回退:將list中最後一個節點刪除
		list.remove(list.size() - 1); 
		return listAll;
	}
	
	public static void main(String[] args) {
		
		FindPathEqualNum find = new FindPathEqualNum();
		
		TreeNode root = find.new TreeNode(10);
		TreeNode node1 = find.new TreeNode(5);
		TreeNode node2 = find.new TreeNode(12);
		TreeNode node3 = find.new TreeNode(4);
		TreeNode node4 = find.new TreeNode(7);
		
		root.left = node1;
		root.right = node2;
		
		node1.left = node3;
		node1.right = node4;
		
		ArrayList<ArrayList<Integer>> findPath = find.findPath(root, 22);
		System.out.println(Arrays.toString(findPath.toArray()));  // [[10, 5, 7], [10, 12]]
	}
}