1. 程式人生 > >LeetCode572. Subtree of Another Tree (另一個棵樹的子樹)

LeetCode572. Subtree of Another Tree (另一個棵樹的子樹)

原題

Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree s could also be considered as a subtree of itself.

Example 1:
Given tree s:

     3
    / \
   4   5
  / \
 1   2

Given tree t:

   4 
  / \
 1   2

Return true, because t has the same structure and node values with a subtree of s.

Example 2:
Given tree s:

     3
    / \
   4   5
  / \
 1   2
    /
   0

Given tree t:

   4
  / \
 1   2

Return false.

Reference Answer

Method one: DFS + DFS

容易想到,要判斷一個樹是不是另外一個樹的子樹,那麼可以通過判斷和這個數的任意子樹是否相等的方式來做。那麼就和100. Same Tree挺像了。所以這個題的做法就是在判斷兩棵樹是否相等的基礎上,新增上任意子樹是否相等的判斷。

任意子樹是否相等判斷的方式是:

  1. 當前兩棵樹是否相等
  2. s的左孩子和t是否相等
  3. t的左孩子和t是否相等

這三個條件是 的關係。
注意,判斷兩個數是否相等是與的關係。
判斷是否是子樹與是否是相同的樹的程式碼簡直是對稱美啊~

這裡很值得注意的一個地方時,無論是方法一還是方法二,都用瞭如下程式碼先從樹結構進行判定:

if not s and not t:
    return True
if not s or not t:
    return False

其依據是“在當節點為空的時候給一個“#”表示,這樣就能表示出不同的子樹,因此只需要遍歷一次就能得到結果。每次遍歷到樹的結尾的時候能夠按照#區分,另外每個樹的節點值之間用","分割。”

Code

class Solution:
    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """
# 1. method one: DFS + DFS

        if not s and not t:
            return True
        if not s or not t:
            return False
        return self.isSameTree(s,t) or self.isSubtree(s.left, t) or self.isSubtree(s.right, t)
    
    
    def isSameTree(self, s, t):
        if not s and not t:
            return True
        if not s or not t:
            return False
        return s.val == t.val and self.isSameTree(s.left, t.left) and self.isSameTree(s.right, t.right)
            

Method Two: BFS + DFS

因為s的每個節點都可能成為和t相等的根節點,那麼我們使用BFS來遍歷每個節點,然後對每個節點進行判斷就好了。

參考答案採用了colletions.deque()暫存節點,這種方式比採用list更巧妙,先進先出也完全符合程式設定。

class Solution:
    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """  
# 2. method two: BFS + DFS
        if not s and not t:
            return True
        if not s or not t:
            return False
        que = collections.deque()
        que.append(s)
        while que:
            node = que.popleft()
            if not node:
                continue
            if self.isSameTree(node, t):
                return True
            que.append(node.left)
            que.append(node.right)
        return False
            

    def isSameTree(self, s, t):
        if not s and not t:
            return True
        if not s or not t:
            return False
        return s.val == t.val and self.isSameTree(s.left, t.left) and self.isSameTree(s.right, t.right)        

Note

  • 自己嘗試著用後續遍歷進行判定,儲存兩棵樹節點值,進行判定的依據是認為是子樹結構必然儲存在後續遍歷開始,沒通過的原因正是在於該依據有錯誤,當樹結構比較深時,其子結構可能存在中間,這時候子樹結構無法對應原樹結構的開始節點位置。

參考文獻

[1] https://blog.csdn.net/fuxuemingzhu/article/details/71440802