1. 程式人生 > >二叉樹系列3: 二叉樹的路徑問題

二叉樹系列3: 二叉樹的路徑問題

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