题目介绍
描述:翻转一棵二叉树。
示例:
输入:
4
/ \\
2 7
/ \\ / \\
1 3 6 9
输出:
4
/ \\
7 2
/ \\ / \\
9 6 3 1
解题思路:
递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么
对树进行递归反转,第一次实现错误,是在交换之前,中间要加个变量过度一下
自己的解法实现
def invertTree(self, root):
if not root: return None
left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left, root.right = right, left
return root
网上比较优秀的解法
解法一
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子结点先开始翻转。如果当前遍历到的节点root的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以root 为根节点的整棵子树的翻转。
def invertTree(self, root):
# 递归函数的终止条件,节点为空时返回
if not root: return None
# 将当前节点的左右子树交换
root.left, root.right = root.right, root.left
# 递归交换当前节点的 左子树和右子树
self.invertTree(root.left)
self.invertTree(root.right)
return root
解法二
广度优先遍历需要额外的数据结构--队列,来存放临时遍历到的元素。 深度优先遍历的特点是一竿子插到底,不行了再退回来继续;而广度优先遍历的特点是层层扫荡。 所以,我们需要先将根节点放入到队列中,然后不断的迭代队列中的元素。 对当前元素调换其左右子树的位置,然后:
判断其左子树是否为空,不为空就放入队列中 判断其右子树是否为空,不为空就放入队列中
def invertTree3(self, root):
if not root: return []
# 将二叉树中的节点逐层放入队列中,再迭代处理队列中的元素
stack = [root]
while stack:
# 每次都从队列中拿一个节点,并交换这个节点的左右子树
node = stack.pop(0)
node.left, node.right = node.right, node.left
# 如果当前节点的左子树不为空,则放入队列等待后续处理
if node.left:
stack.append(node.left)
# 如果当前节点的右子树不为空,则放入队列等待后续处理
if node.right:
stack.append(node.right)
return root
def invertTree4(self, root):
from collections import deque
if not root: return None
queue = deque([root])
while queue:
node = queue.popleft()
node.left, node.right = node.right, node.left
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
解法三
递归终止的条件: 当要翻转的节点是空,停止翻转,返回空节点。 返回值: 虽然对 root 的左右子树都进行了翻转,但是翻转后的二叉树的根节点不变,故返回 root 节点。 函数内容 root 节点的新的左子树:是翻转了的 root.right => 即 root.left = invert(root.right); root 节点的新的右子树:是翻转了的 root.left => 即 root.right = invert(root.left);
def invertTree5(self, root):
if not root: return None
root.left, root.right = self.invertTree5(root.right), self.invertTree5(root.left)
return root