欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【图解二叉树面试题】如何翻转一颗二叉树??

程序员文章站 2024-01-15 12:42:34
...

目录

题目描述

递归

迭代


题目描述

题目地址:https://leetcode-cn.com/problems/invert-binary-tree/

翻转一棵二叉树。
示例:
输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

备注:

这个问题是受到 Max Howell 的 原问题 启发的 :
谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。

递归

我们在做二叉树题目时候,第一想到的应该是用递归来解决。
仔细看下题目的输入输出,输出的左右子树的位置跟输入正好是相反的,于是我们可以递归的交换左右子树来完成这道题。
看一下动画就明白了:

 

【图解二叉树面试题】如何翻转一颗二叉树??


其实就是交换一下左右节点,然后再递归的交换左节点,右节点
根据动画图我们可以总结出递归的两个条件如下:

  1. 终止条件:当前节点为null时返回

  2. 交换当前节点的左右节点,再递归的交换当前节点的左节点,递归的交换当前节点的右节点

     

时间复杂度:每个元素都必须访问一次,所以是O(n)

空间复杂度:最坏的情况下,需要存放O(h)个函数调用(h是树的高度),所以是O(h)

代码实现如下:
java实现:

class Solution {
	public TreeNode invertTree(TreeNode root) {
		//递归函数的终止条件,节点为空时返回
		if(root==null) {
			return null;
		}
		//下面三句是将当前节点的左右子树交换
		TreeNode tmp = root.right;
		root.right = root.left;
		root.left = tmp;
		//递归交换当前节点的 左子树
		invertTree(root.left);
		//递归交换当前节点的 右子树
		invertTree(root.right);
		//函数返回时就表示当前这个节点,以及它的左右子树
		//都已经交换完了
		return root;
	}
}

python实现:

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)
		# 函数返回时就表示当前这个节点,以及它的左右子树
		# 都已经交换完了		
		return root

迭代

递归实现也就是深度优先遍历的方式,那么对应的就是广度优先遍历。
广度优先遍历需要额外的数据结构--队列,来存放临时遍历到的元素。
深度优先遍历的特点是一竿子插到底,不行了再退回来继续;而广度优先遍历的特点是层层扫荡。
所以,我们需要先将根节点放入到队列中,然后不断的迭代队列中的元素。   
对当前元素调换其左右子树的位置,然后:

  • 判断其左子树是否为空,不为空就放入队列中

  • 判断其右子树是否为空,不为空就放入队列中

动态图如下:   

【图解二叉树面试题】如何翻转一颗二叉树??

深度优先遍历和广度优先遍历,从动画图中看起来很类似,这是因为演示的树层数只有三层。   

时间复杂度:同样每个节点都需要入队列/出队列一次,所以是O(n)

空间复杂度:最坏的情况下会包含所有的叶子节点,完全二叉树叶子节点是n/2个,所以时间复杂度是0(n)

代码实现如下:
java实现:

class Solution {
	public TreeNode invertTree(TreeNode root) {
		if(root==null) {
			return null;
		}
		/将二叉树中的节点逐层放入队列中,再迭代处理队列中的元素
		LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
		queue.add(root);
		while(!queue.isEmpty()) {
			//每次都从队列中拿一个节点,并交换这个节点的左右子树
			TreeNode tmp = queue.poll();
			TreeNode left = tmp.left;
			tmp.left = tmp.right;
			tmp.right = left;
			//如果当前节点的左子树不为空,则放入队列等待后续处理
			if(tmp.left!=null) {
				queue.add(tmp.left);
			}
			//如果当前节点的右子树不为空,则放入队列等待后续处理
			if(tmp.right!=null) {
				queue.add(tmp.right);
			}
			
		}
		//返回处理完的根节点
		return root;
	}
}

python实现:

class Solution(object):
	def invertTree(self, root):
		"""
		:type root: TreeNode
		:rtype: TreeNode
		"""
		if not root:
			return None
		# 将二叉树中的节点逐层放入队列中,再迭代处理队列中的元素
		queue = [root]
		while queue:
			# 每次都从队列中拿一个节点,并交换这个节点的左右子树
			tmp = queue.pop(0)
			tmp.left,tmp.right = tmp.right,tmp.left
			# 如果当前节点的左子树不为空,则放入队列等待后续处理
			if tmp.left:
				queue.append(tmp.left)
			# 如果当前节点的右子树不为空,则放入队列等待后续处理	
			if tmp.right:
				queue.append(tmp.right)
		# 返回处理完的根节点
		return root

欢迎扫描关注公众号 有更多图解的算法面试题等你哦~

【图解二叉树面试题】如何翻转一颗二叉树??