劍指Offer之樹的子結構


題目描述

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

基本思路

  要查找樹A是否存在和樹B結構一樣的子樹,我們可以分成兩步:第一步在樹A中找到和樹B的根節點的值一樣的節點R,第二步再判斷樹A中以R為根節點的子樹是不是包含和樹B一樣的結構。

 

  如上圖所示:首先我們試着在樹A中找到值為8(樹B的根節點的值)的節點。從樹A的根節點開始遍歷,我們發現它的根節點就是8。接着我們就去判斷樹A的根節點下面的子樹是不是含有和樹B一樣的結構。在樹A中,根節點的左子節點的值是8,而樹B的根節點的左子節點是9,對應的兩個節點不同。

  因此,我們仍需要遍歷樹A,接着查找值為8的節點。我們在樹的第二層找到了一個值為8的節點,然后進行第二步判斷,即判斷這個節點下面的子樹是否含有和樹B一樣結構的子樹。於是我們遍歷這個節點下面的子樹,先后得到兩個子節點9和2,這和B樹的結構完全相同。此時我們在樹A中找到了一個和樹B的結構一樣的子樹,因此樹B是樹A的子結構。

  第一步在樹A中查找與根節點一樣的節點,實際上就是樹的遍歷,可以采用遞歸的方式,代碼如下:

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
       if(root2==null) return false;
        if(root1==null && root2!=null) return false;      
        boolean flag = false;
        if(root1.val==root2.val){
            flag = isSubTree(root1,root2);
        }
        if(!flag){
            flag = HasSubtree(root1.left, root2);
            if(!flag){
                flag = HasSubtree(root1.right, root2);
            }
        }
        return flag;
    }

  第二步是判斷樹A中以R為根節點的子樹是不是和樹B具有相同的結構。同樣,我們也可以用遞歸的思路來考慮:如果節點R的值和樹B的根節點不相同,則以R為根節點的子樹和樹B肯定不具有相同的結點;如果它們的值相同,則遞歸地判斷它們各自的左右節點的值是不是相同。遞歸的終止條件是我們到達了樹A或者樹B的葉節點,代碼如下:

private boolean isSubTree(TreeNode root1, TreeNode root2) {
        if(root2==null) return true;
        if(root1==null && root2!=null) return false;      
        if(root1.val==root2.val){
            return isSubTree(root1.left, root2.left) &&  isSubTree(root1.right, root2.right);
        }else{
        return false;
        }
    }

  上述代碼有多處判斷節點是不是NULL,這樣做是為了避免試圖訪問空節點而造成的程序崩潰,同時設置了遞歸調用的退出條件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM