层序遍历
层序遍历二叉树,就是从左到右一层一层去遍历,需要借用队列数据结构来辅助实现。在遍历二叉树时,遍历一层将该层所有节点加入队列,并记录当前队列的长度,然后再pop出去这么长的元素,在pop的过程中,pop出去一个元素,相应地把该元素对应的左右孩子加入队列(保证左右孩子不为空),以此循环直到队列为空。
from collections import deque
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
queue = deque([root])
result = []
while queue:
level = []
size = len(queue) # 一层所包含的节点
# 将当前层所有节点从队列中输出,并将所有的子节点加入队列
for _ in range(size):
cur = queue.popleft()
level.append(cur.val)
if cur.left: # 将当前层的下一层的左孩子放入队列中
queue.append(cur.left)
if cur.right: # 将当前层的下一层的右孩子放入队列中
queue.append(cur.right)
result.append(level)
return result
翻转二叉树
解法一:递归法
class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
if not root:
return None
# 前序遍历
root.left,root.right = root.right,root.left # 中
self.invertTree(root.left) #左
self.invertTree(root.right) #右
# 后序遍历
self.invertTree(root.left) #左
self.invertTree(root.right) #右
root.left,root.right = root.right,root.left # 中
# 中序遍历
self.invertTree(root.left) # 左
root.left,root.right = root.right,root.left # 中
self.invertTree(root.left) #左(此时的左边已经是翻转过来的右边了)
return root
解法二:迭代法
class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
if not root:
return None
stack = [root]
while stack:
cur = stack.pop()
# 前序遍历
cur.left,cur.right = cur.right,cur.left # 中
if cur.left: # 左
stack.append(cur.left)
if cur.right: # 右
stack.append(cur.right)
# 后序遍历
if cur.left: # 左
stack.append(cur.left)
if cur.right: # 右
stack.append(cur.right)
cur.left,cur.right = cur.right,cur.left # 中
# 中序遍历
if cur.left: # 左
stack.append(cur.left)
cur.left,cur.right = cur.right,cur.left # 中
if cur.left: # 左(此时的左边已经是翻转过来的右边了)
stack.append(cur.left)
return root
解法三:广度优先遍历(层序遍历)
class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
if not root:
return None
queue = collections.deque([root])
while queue:
size = len(queue)
for _ in range(size):
cur = queue.popleft()
cur.left,cur.right = cur.right,cur.left # 交换左右孩子
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return root
对称二叉树
层序遍历(本人自己写出来的)
这里我的想法就是,一个树对称,说明除了根节点以外他下面每一层都应该是偶数,不然不可能对称。那么,利用层序遍历就可以得到每一层的元素,翻转每一层是否与原来相等岂不就能直到是否为对称的了。
上述大致的思路是没问题的,但是存在一种不对称但是元素翻转之后相等的情况就是元素虽然相等但是结构不一样。
为了标记这种某层存在空节点的情况,可以将空节点赋值一个固定的元素(因为本题的元素取值范围在-100至100之间,所以我选择赋值为101,当然也可以赋值为None之类的(这里的赋值是append进层结果集,不是在原二叉树上操作)),这样就能够处理这种结构不相等的情况了。
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
queue = collections.deque([root])
while queue:
size = len(queue)
level = []
if size != 1 and size % 2 != 0:
return False
else:
for _ in range(size):
cur = queue.popleft()
if cur:
level.append(cur.val)
else:
level.append(101)
if cur:
queue.append(cur.left)
queue.append(cur.right)
if level != level[::-1]:
return False
return True
递归法
实现思路就是对于当前节点判断它的两个子节点是否相同以外,还需要判断子节点所指向的下面四个节点是否对称(即左子树的左孩子与右子树的右孩子、左子树的右孩子与右子树的左孩子是否相等),然后根据递归法依次递归即可判断以根节点为中心的两边子树是否对称。
我是这么理解的,往下遍历总能转换成两个子树的内侧与外侧是否相等(画图很好理解,实在不行记住就行)。
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
return self.compare(root.left,root.right)
def compare(self,left,right):
# 排除空节点的情况
if left == None and right != None:
return False
elif left != None and right == None:
return False
elif left == None and right == None:
return True
# 排除值不同的情况
elif left.val != right.val:
return False
# 左右节点都不为空且数值相同的情况,用递归进行下一层的判断
outer = self.compare(left.left,right.right) #左子树的左孩子与右子树的右孩子需要相同才对称(外侧)
inner = self.compare(left.right,right.left) #左子树的右孩子与右子树的左孩子需要相同才对称(内侧)
return outer and inner # 同时相同才满足条件
迭代法(使用队列)
这里的思想和递归法的思想一致,只不过用队列来实现,通过依次判断内侧与外侧是否相同来确定是否对称。
import collections
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:
return True
queue = collections.deque()
queue.append(root.left) #将左子树头结点加入队列
queue.append(root.right) #将右子树头结点加入队列
while queue: #接下来就要判断这这两个树是否相互翻转
leftNode = queue.popleft()
rightNode = queue.popleft()
if not leftNode and not rightNode: #左节点为空、右节点为空,此时说明是对称的
continue
#左右一个节点不为空,或者都不为空但数值不相同,返回false
if not leftNode or not rightNode or leftNode.val != rightNode.val:
return False
queue.append(leftNode.left) #加入左节点左孩子
queue.append(rightNode.right) #加入右节点右孩子
queue.append(leftNode.right) #加入左节点右孩子
queue.append(rightNode.left) #加入右节点左孩子
return True