https://leetcode-cn.com/problems/symmetric-tree/
1. 描述
Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
2. 解决
2.1 递归——DFS(深度优先)
递归思想:
- 左孩子的左孩子 = 右孩子的右孩子 (e.g.:1.left.left == 1.right.right)
- 左孩子的右孩子 = 右孩子的左孩子 (e.g.:1.left.right == 1.right.left)
递归出口:
- 左右结构不同(比如:左孩子存在但右孩子不存在)
- 递归思想中的等式不成立
时间复杂度: O(n),因为要遍历 n 个节点。
空间复杂度: O(n),空间复杂度是递归的深度,也就是跟树高度有关,最坏情况下树变成一个链表结构,高度是n。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root: # 无根,直接True
return True
def dfs(left, right): # 递归函数
if not (left or right): # 左右孩子都不存在,即只有根节点→ True
return True
if not (left and right): # 左右结构不同→ False
return False
if left.val != right.val: # 左右结构相同但值不同→ False
return False
# 开始递归比较“左孩子的左孩子” 与 “右孩子的右孩子”,“左孩子的右孩子” 与 “右孩子的左孩子”
return dfs(left.left, right.right) and dfs(left.right, right.left)
# 调用递归函数
return dfs(root.left, root.right)
2.2 迭代——BFS(广度优先)
思想还是:
- 左孩子的左孩子 = 右孩子的右孩子 (e.g.:1.left.left == 1.right.right)
- 左孩子的右孩子 = 右孩子的左孩子 (e.g.:1.left.right == 1.right.left)
只不过不通过递归来表示,可以使用队列 :
- 将根节点的两个孩子放入队列
- 每次 pop 出两个节点,并进行比较:(注意pop()弹出的是最后一个,pop(0)弹出的是第一个)
- 都为空→ 跳出本次循环continue
- 一个空一个非空→ False
- 都非空,但值不同→ False
- 都非空,且值相同→ 更新队列
- 更新队列:将下一层依次加入队列(跟递归思想一致):
- 左孩子的左孩子
- 右孩子的右孩子
- 左孩子的右孩子
- 右孩子的左孩子
时间复杂度: O(n)。
空间复杂度: O(n)。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
# 无根 or 根无孩子→ True
if not root or not (root.left or root.right):
return True
# 将根节点的两个孩子放入队列
queue = [root.left, root.right]
while queue:
# 每次 pop 两个节点进行比较
left = queue.pop(0)
right = queue.pop(0)
# 无孩子→ 跳出本次循环continue
if not (left or right):
continue
# 结构不同→ False
if not (left and right):
return False
# 结构同,值不同→ False
if left.val != right.val:
return False
# 将左节点的左孩子, 右节点的右孩子放入队列
queue.append(left.left)
queue.append(right.right)
# 将左节点的右孩子,右节点的左孩子放入队列
queue.append(left.right)
queue.append(right.left)
return True