一.问题描述
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
Note:
Bonus points if you could solve it both recursively and iteratively.
二.解题思路
这种题目基本都是有递归和迭代两种方法的,同时一般来首。。。递归一般都比迭代容易不少。。
先讲思路吧,首先知道啥是对称数,就是沿着root,把右子树来个180度翻转,发现和左子树一样,就是对称树。
因为你要对比两边子树的情况,所以你肯定得同时处理两个子树(或者说两个节点)。
要解决这个问题,首先是得定位到底是左边哪个node和右边哪个node比。
看图很容易知道:
假设当前的左node为left,右node为right,这两个节点是要对比的对称节点。
那么下一个你要对比的组就是 left.left == right.right 和 left.right==right.left。知道了这个就谈具体实现吧。
1.递归:
我们知道我们需要两个点left 和 right 来比较,因此递归接受两个参数,left 和 right 为当次需要对比的两个点,返回值为以它们俩为根的子树在整个树来看是不是对称的。
left和right传进来有几种情况:
<1. left和right都为None,说明到了叶子节点,是递归的结束,返回True
<2. left和right某一个为None,另外一个不为None, 剪枝操作,不管它们俩的子树如何,都不可能是对称的了。
<3. left和right都不为空并且它们俩值相等,检测它们的子树. 递归 isSymmetric(left.right,right.left) and isSymmetric(left.left, right.right)。
2.迭代
说实话这种题目完全就是适合递归,非要用迭代只能说,来吧。
其实思路和之前都一样,就是要用堆栈来存,因为要同时对比两个节点,所以用俩堆栈,一个存左子树一个存右子树,然后这俩个堆栈入栈顺序要相反。一个要先入左再入右,另一个先入右再入左(和我们上面说的一样),这样子出栈对比的就是正确的对比对象。
其他的一些细节其实和递归要注意的地方差不多。
也可以用一个栈来解决,每次就得弹出两个出来。然后存4个,顺序就要注意一下,要对比的两个得连续入栈。不过上面的好理解一点。
PS:当root为空时这个树竟然是对称的,我是佛了。
更多leetcode算法题解法: 专栏 leetcode算法从零到结束
给出三种实现。
三.源码
1.递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
def isSymmetricHelper(left,right):
if not left and not right:return True
if not right or not left:return False
if left.val!=right.val:return False
return isSymmetricHelper(left.left,right.right) and \
isSymmetricHelper(left.right,right.left)
if not root:return True
return isSymmetricHelper(root.left,root.right)
2.迭代,双栈
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:return True
left,right=[root.left],[root.right]
res=True
while left and right:
node1,node2=left.pop(),right.pop()
if not node1 and node2 or node1 and not node2:
res=False
break
if node1 and node2:
if node1.val==node2.val:
left.append(node1.left)
left.append(node1.right)
right.append(node2.right)
right.append(node2.left)
else:
res=False
break
return len(left)==len(right) and res
3.迭代,单栈
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:return True
stack=[root.left,root.right]
res=True
while stack:
node1,node2=stack.pop(),stack.pop()
if not node1 and node2 or node1 and not node2:
res=False
break
if node1 and node2:
if node1.val==node2.val:
stack.append(node1.left)
stack.append(node2.right)
stack.append(node1.right)
stack.append(node2.left)
else:
res=False
break
return res
PS:像迭代的时候 res=False break这里其实可以直接返回 return False,然后把最后的return去掉,但是我觉得最好还是不要这样,因为很多时候我们一下子没考虑到所有情况,可能会导致函数没返回,特别是在递归的时候,导致的问题会很可怕。