1. 程式人生 > >[劍指offer學習心得]之:二叉樹中和為某一值的路徑

[劍指offer學習心得]之:二叉樹中和為某一值的路徑

題目:輸入一棵二叉樹和一個整數, 打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。

二叉樹結點的定義:

public static class BinaryTreeNode {
    int value;
    BinaryTreeNode left;
    BinaryTreeNode right;
}

解題思路:

由於路徑是從根結點出發到葉結點, 也就是說路徑總是以根結點為起始點,因此我們首先需要遍歷根結點。在樹的前序、中序、後序三種遍歷方式中,只有前序遍歷是首先訪問根結點的。

當用前序遍歷的方式訪問到某一結點時, 我們把該結點新增到路徑上,並累加該結點的值。如果該結點為葉結點並且路徑中結點值的和剛好等於輸入的整數, 則當前的路徑符合要求,我們把它打印出來。如果當前結點不是葉結點,則繼續訪問它的子結點。當前結點訪問結束後,遞迴函式將自動回到它的父結點。因此我們在函式退出之前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父結點時路徑剛好是從根結點到父結點的路徑。

不難看出儲存路徑的資料結構實際上是一個枝, 因為路徑要與遞迴呼叫狀態一致, 而遞迴呼叫的本質就是一個壓棧和出棧的過程。

測試用例

  1. 功能測試(二叉樹中有一條、多條符合條件的路徑,二叉樹中沒有符合條件的路徑)
  2. 特殊輸入測試(指向二叉樹根結點的為null)

程式碼

import java.util.ArrayList;
import java.util.List;

public class FindPath {

    public static class BinaryTreeNode{
        int value;
        BinaryTreeNode left;
        BinaryTreeNode right;
    }

    public
static void findPath(BinaryTreeNode root,int expectSum){ List<Integer> list=new ArrayList<Integer>(); if(root!=null) { findPath(root,0,expectSum,list); } } public static void findPath(BinaryTreeNode root,int curSum,int expectSum,List<Integer> result){ if
(root!=null){ curSum+=root.value; result.add(root.value); boolean isLeaf=root.left==null&&root.right==null; if(curSum==expectSum&&isLeaf){ System.out.println(result); }else if(curSum<expectSum){ findPath(root.left,curSum,expectSum,result); findPath(root.right,curSum,expectSum,result); } result.remove(result.size()-1); } } public static void main(String[] args){ // 10 // / \ // 5 12 // /\ // 4 7 BinaryTreeNode root = new BinaryTreeNode(); root.value = 10; root.left = new BinaryTreeNode(); root.left.value = 5; root.left.left = new BinaryTreeNode(); root.left.left.value = 4; root.left.right = new BinaryTreeNode(); root.left.right.value = 7; root.right = new BinaryTreeNode(); root.right.value = 12; // 有兩條路徑上的結點和為22 System.out.println("findPath(root, 22);"); findPath(root, 22); // 沒有路徑上的結點和為15 System.out.println("findPath(root, 15);"); findPath(root, 15); // 有一條路徑上的結點和為19 System.out.println("findPath(root, 19);"); findPath(root, 19); // 5 // / // 4 // / // 3 // / // 2 // / // 1 BinaryTreeNode root2 = new BinaryTreeNode(); root2.value = 5; root2.left = new BinaryTreeNode(); root2.left.value = 4; root2.left.left = new BinaryTreeNode(); root2.left.left.value = 3; root2.left.left.left = new BinaryTreeNode(); root2.left.left.left.value = 2; root2.left.left.left.left = new BinaryTreeNode(); root2.left.left.left.left.value = 1; // 有一條路徑上面的結點和為15 System.out.println("findPath(root2, 15);"); findPath(root2, 15); // 沒有路徑上面的結點和為16 System.out.println("findPath(root2, 16);"); findPath(root2, 16); //1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 BinaryTreeNode root3 = new BinaryTreeNode(); root3.value = 1; root3.right = new BinaryTreeNode(); root3.right.value = 2; root3.right.right = new BinaryTreeNode(); root3.right.right.value = 3; root3.right.right.right = new BinaryTreeNode(); root3.right.right.right.value = 4; root3.right.right.right.right = new BinaryTreeNode(); root3.right.right.right.right.value = 5; // 有一條路徑上面的結點和為15 System.out.println("findPath(root3, 15);"); findPath(root3, 15); // 沒有路徑上面的結點和為16 System.out.println("findPath(root3, 16);"); findPath(root3, 16); // 樹中只有1個結點 BinaryTreeNode root4 = new BinaryTreeNode(); root4.value = 1; // 有一條路徑上面的結點和為1 System.out.println("findPath(root4, 1);"); findPath(root4, 1); // 沒有路徑上面的結點和為2 System.out.println("findPath(root4, 2);"); findPath(root4, 2); // 樹中沒有結點 System.out.println("findPath(null, 0);"); findPath(null, 0); } }