二叉樹系列3: 二叉樹的路徑問題
阿新 • • 發佈:2019-01-26
1 輸出根節點到葉子節點的路徑
TreeNode.java
package BinaryTree;
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(TreeNode l, TreeNode r, int v) {
left = l;
right = r;
val = v;
}
public TreeNode(int v) {
val = v;
}
}
【核心】BinaryTreeTest.java
public class BinaryTreeTest {
/**
* 將從跟節點到所有葉子節點的所有路徑儲存到paths中*/
public void printPath_Root2Leaf(TreeNode t,ArrayList<TreeNode> path, ArrayList<List<TreeNode>> paths) {
if(t == null){
return;
}
path.add(t);
// 如果t就是葉子節點,則將 path 新增到 paths
if(t.left == null && t.right == null){
paths.add(path);
return;
}else {
if(t.left != null){
ArrayList<TreeNode> leftPath = (ArrayList<TreeNode>) path.clone();
printPath_Root2Leaf(t.left, leftPath, paths);
}
if (t.right != null){
ArrayList<TreeNode> rightPath = (ArrayList<TreeNode>) path.clone();
printPath_Root2Leaf(t.right, rightPath, paths);
}
// 幫助GC
path = null;
}
}
【測試】Main.java
public class Main {
public static void main(String[] args) {
/***
* 新建一個二叉樹:
*
* 15
* / \
* 12 25
* / \
* 9 13
* ***/
TreeNode root = new TreeNode(15);
TreeNode l = new TreeNode(12);
root.left = l;
TreeNode r = new TreeNode(25);
root.right = r;
TreeNode ll = new TreeNode(9);
TreeNode lr = new TreeNode(13);
l.left = ll;
l.right = lr;
BinaryTreeTest bTreeTest = new BinaryTreeTest();
ArrayList<TreeNode> path = new ArrayList<>();
ArrayList<List<TreeNode>> paths = new ArrayList<>();
bTreeTest.printPath_Root2Leaf(root, path, paths);
for (List<TreeNode> list : paths) {
for (TreeNode treeNode : list) {
System.out.printf("%-4d", treeNode.val);
}
System.out.println();
}
}
}
結果:
15 12 9
15 12 13
15 25
2 輸出給定節點到根節點的路徑
其實就是一個先序遍歷去查詢,一邊查詢一邊記錄走過的節點,如果找到就把相應的路徑返回。
/** 包裝方法 */
public ArrayList<TreeNode> printPath(TreeNode t, int val) {
ArrayList<TreeNode> path = new ArrayList<>();
return printPath(t, val, path);
}
/** 輸出給定節點到根節點的路徑 */
private ArrayList<TreeNode> printPath(TreeNode t, int val, ArrayList<TreeNode> path) {
if (t == null) {
return null;
}
path.add(t);
// 如果找到就直接返回
if (val == t.val) {
//System.out.println("Find!");
return path;
} else {
// 如果沒有找到則搜尋它的左子樹
ArrayList<TreeNode> leftPath = (ArrayList<TreeNode>) path.clone();
ArrayList<TreeNode> lRet = printPath(t.left, val, leftPath);
if (lRet != null) {
// 說明在做子樹中找到了這個點,則返回
path = null;
return lRet;
}
// 如果在左子樹沒有找到,則搜尋右子樹
else {
ArrayList<TreeNode> rightPath = (ArrayList<TreeNode>) path.clone();
ArrayList<TreeNode> rRet = printPath(t.right, val, rightPath);
if (rRet != null) {
path = null;
return rRet;
}
// 說明右子樹也沒有找到
else {
path = null;
return null;
}
}
}
}
將上面的Main進行一點修改,測試:
BinaryTreeTest bTreeTest = new BinaryTreeTest();
ArrayList<TreeNode> path;
path = bTreeTest.printPath(root, 9);
if (path != null) {
for (TreeNode treeNode : path) {
System.out.printf("%-4d", treeNode.val);
}
System.out.println();
}else {
System.out.println("Cannot find!");
}
path = bTreeTest.printPath(root, 25);
if (path != null) {
for (TreeNode treeNode : path) {
System.out.printf("%-4d", treeNode.val);
}
System.out.println();
}else {
System.out.println("Cannot find!");
}
path = bTreeTest.printPath(root, 33);
if (path != null) {
for (TreeNode treeNode : path) {
System.out.printf("%-4d", treeNode.val);
}
System.out.println();
}else {
System.out.println("Cannot find!");
}
結果:
15 12 9
15 25
Cannot find!
3 在二叉樹中找出和為某一值的所有路徑
前面都已經介紹了列印所有根節點到葉子節點路徑的方法了,這個無非就是加個計算的步驟而已。只不過為了減少計算量,在將一個節點add進path之前,判斷sum,如果sum大於target,則這條路徑沒必要再計算下去了。
private ArrayList<List<TreeNode>> printPathWithsum(TreeNode t, int sum, ArrayList<TreeNode> path,
ArrayList<List<TreeNode>> paths) {
if (t == null) {
return null;
}
if (t.val == sum) {
path.add(t);
paths.add(path);
return paths;
} else if (t.val > sum) {
return null;
} else {
path.add(t);
if (t.left != null) {
ArrayList<TreeNode> leftPath = (ArrayList<TreeNode>) path.clone();
printPathWithsum(t.left, sum - t.val, leftPath, paths);
}
if (t.right != null) {
ArrayList<TreeNode> rightPath = (ArrayList<TreeNode>) path.clone();
printPathWithsum(t.right, sum - t.val, rightPath, paths);
}
}
return paths;
}
測試:
package BinaryTree;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
/***
* 新建一個二叉樹:
*
* 15
* / \
* 12 25
* / \
* 9 13
* ***/
TreeNode root = new TreeNode(15);
TreeNode l = new TreeNode(12);
root.left = l;
TreeNode r = new TreeNode(25);
root.right = r;
TreeNode ll = new TreeNode(9);
TreeNode lr = new TreeNode(13);
l.left = ll;
l.right = lr;
BinaryTreeTest testTree = new BinaryTreeTest();
ArrayList<List<TreeNode>> paths = testTree.printPathWithsum(root, 40);
System.out.println("*** the sum is 40 ***");
for (List<TreeNode> list : paths) {
for (TreeNode treeNode : list) {
System.out.printf("%-5d", treeNode.val);
}
System.out.println();
}
}
}
結果:
*** the sum is 40 ***
15 12 13
15 25