1. 程式人生 > >劍指Offer刷題筆記(java實現)_26.樹的子結構

劍指Offer刷題筆記(java實現)_26.樹的子結構

題目描述

  輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)。

其實思路很簡單:我們的演算法就通過比較即可,因為是樹的遍歷比較所以第一時間想到了遞迴

先假設母樹為A,子樹為B

(1)我們先去判斷節點的第一個點的值是否相同,如果相同則進一步遍歷以這個節點相同的左右子樹是否和B的起點的左右子樹的值都相同

(2)如果比較的當前頭結點的值都不同我們就要去A樹的左右子樹找和B樹相同的值,如果相同則去遍歷到相應的值遍歷到後再跳到步驟(1):

package treeAhavaTreeB_26;

import sun.reflect.generics.tree.Tree;

public class TreeAHasTreeB {
    public static void main(String[] args) {
        int[] arrTreeA = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
        int[] arrTreeB=new int[]{0};
        printTreeDFS(buildTree(arrTreeA, 1));
        printTreeDFS(buildTree(arrTreeB, 1));
      System.out.println(isContain(buildTree(arrTreeA,1),buildTree(arrTreeB,1)));
    }


    /*
     * 建二叉樹:按照相應的座標順序重建
     * */
    public static TreeRoot buildTree(int[] arr, int index) {
        if (index <= arr.length - 1) {
            TreeRoot treeRoot = new TreeRoot();
            treeRoot.value = arr[index];

            treeRoot.leftRoot = buildTree(arr, index * 2);

            treeRoot.rightRoot = buildTree(arr, index * 2 + 1);
            return treeRoot;
        }
        return null;
    }


    /*
     *   前序遍歷
     *   遞迴遍歷
     * */
    public static void printTreeDFS(TreeRoot treeRoot) {
        if (treeRoot != null) {
            System.out.println(treeRoot.value);
            printTreeDFS(treeRoot.leftRoot);
            printTreeDFS(treeRoot.rightRoot);
        }
    }


    //核心演算法:是否包含相應的子樹
    public static boolean isContain(TreeRoot treeRootA, TreeRoot treeRootB) {
        boolean result = false;
        if (treeRootA != null && treeRootB != null) {
            //(1).判斷每個結點是否相同
               if (treeRootA.value==treeRootB.value){
                  result= everyPointSame(treeRootA,treeRootB);
               }
            //(2).不同則去遍歷別的節點
               if (!result)
                   result=isContain(treeRootA.leftRoot,treeRootB);
               if (!result)
                   result=isContain(treeRootA.rightRoot,treeRootB);
        }
        return result;
    }

    private static boolean everyPointSame(TreeRoot treeRootA, TreeRoot treeRootB) {
        //前兩個if語句一定要這樣的順序,因為先判斷b是否空,為空不管a是否為空都相當於包含了,所以返回true
        //如果判斷到第二個語句,說明b不為空,若a為空,說明不包含,結束,所以返回false
        if (treeRootB==null){
             return true;
         }
         if (treeRootA==null){
             return false;
         }
         if (treeRootA.value!=treeRootB.value){
             return false;
         }
        //遞迴核心演算法
       return everyPointSame(treeRootA.leftRoot,treeRootB.leftRoot)&& everyPointSame(treeRootA.rightRoot,treeRootB.rightRoot);
    }
}


class TreeRoot {
    int value;
    TreeRoot leftRoot;
    TreeRoot rightRoot;
}