Description
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following [1,2,2,null,3,null,3] is not:
1
/ \
2 2
\ \
3 3
sln1
通過深度優先搜索去遍歷一棵樹,有三種可選的順序,分別是前序,中序和後序。這裏的前中後是指要在什麼時候算上父節點,是遍歷子節點前,還是兩個節點之間還是遍歷完子節點之後?在這裏我們隨便選擇一種遍歷順序,我選擇了後序遍歷。在後續遍歷中,如果我對每個節點都是先遍歷左子節點的話,最終會得到一種樹節點的列表順序。而如果我先遍歷右子節點的話,又會得到一種樹節點的列表順序。如果這兩個順序是相等的,說明這個樹是對稱的。實現代碼如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return root is None or (self.leftFirst(root) == self.rightFirst(root))
def leftFirst(self, root):
if root is None:
return [None]
nodes = []
nodes.extend(self.leftFirst(root.left))
nodes.extend(self.leftFirst(root.right))
nodes.append(root.val)
return nodes
def rightFirst(self, root):
if root is None:
return [None]
nodes = []
nodes.extend(self.rightFirst(root.right))
nodes.extend(self.rightFirst(root.left))
nodes.append(root.val)
return nodes
sln2
在sln1的提交結果分析中,發現這種深度優先搜索的方法僅僅超過了10%+的python結果,說明還有很大的優化空間。不難發現,在sln1中,如果樹是不對稱的,我們還是會把整棵樹遍歷完之後纔會發現,而且是遍歷兩遍。但如果一顆不對稱的樹很深,而且在靠近葉子節點的地方就出現不對稱的情況了,這樣我們其實是能夠更早就發現的。所以我們要想一種方法,能夠實現當樹一旦出現不對稱的情況,我們就不再做無效的計算。
通過參考Discuss中大牛們的解法,看到一種十分易於理解且高效的實現,思路如下:如果一棵樹是對稱的,那麼他的左子樹和右子樹應該互爲鏡像。那麼怎麼判斷左子樹和右子樹互爲鏡像呢,首先是左子樹和右子樹的根節點要相等。其次是左子樹的左子樹要和右子樹的右子樹互爲鏡像(isMirror(root.left.left, root.right.right))同時左子樹的右子樹和右子樹的左子樹要互爲鏡像(isMirror(root.left.right, root.right.left))。那麼,一旦某個子節點不是對稱的,他就會返回給上面的父節點。上面的父節點知道下面已經有不對稱的子樹了,自己已經不可能對稱了,就會不斷把這個消息上傳,至到樹的根節點。所以避免掉了許多無效的操作。利用這種算法,我們成功超過了95%+的python程序。算法實現如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return root is None or self.isMirror(root.left, root.right)
def isMirror(self, nodeA, nodeB):
if nodeA is None and nodeB is None:
return True
if nodeA is None or nodeB is None:
return False
return (nodeA.val == nodeB.val) and self.isMirror(nodeA.left, nodeB.right) and self.isMirror(nodeA.right, nodeB.left)