给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]
方法一:递归解法
递归是处理树结构问题的常用方式,二叉树的问题通常可以通过递归轻松解决。在这道题中,递归的思路是:
- 如果当前节点是
null
,直接返回null
。 - 否则,交换当前节点的左右子树,并递归处理左右子树的翻转。
递归的流程如下:
- 先检查当前节点是否为空,如果为空则直接返回。
- 交换左右子树,将左子树存储在临时变量中,左右互换。
- 递归地对左右子树进行同样的操作。
- 返回根节点。
递归代码实现:
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
// 交换左右子树
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// 递归翻转左右子树
invertTree(root.left);
invertTree(root.right);
return root;
}
}
复杂度分析:
- 时间复杂度:O(n),其中
n
是二叉树中的节点数。每个节点被访问一次,因此总的时间复杂度是线性的。 - 空间复杂度:O(h),其中
h
是二叉树的高度。递归栈的最大深度取决于树的高度,因此空间复杂度与树的高度成正比。在最坏的情况下(树呈现为一条链),高度为n
。
方法二:非递归解法 (BFS)
非递归的解法通常通过遍历二叉树的方式来实现。在这道题中,我们可以采用广度优先搜索(BFS)来逐层交换每个节点的左右子树。具体思路是:
- 使用一个队列存储树中的节点。
- 每次从队列中取出一个节点,交换该节点的左右子树。
- 将交换后的左右子树(非空)依次加入队列,继续遍历直到队列为空。
非递归代码实现:
import java.util.LinkedList;
import java.util.Queue;
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode current = queue.poll();
// 交换当前节点的左右子树
TreeNode temp = current.left;
current.left = current.right;
current.right = temp;
// 将非空的左右子树加入队列
if (current.left != null) {
queue.add(current.left);
}
if (current.right != null) {
queue.add(current.right);
}
}
return root;
}
}
复杂度分析:
- 时间复杂度:O(n),与递归方法相同,每个节点被访问一次。
- 空间复杂度:O(n),使用了一个队列来存储每一层的节点,最坏情况下,队列中的节点数会达到
n/2
(树的最底层节点数),因此空间复杂度为 O(n)。
总结:
- 递归解法:简洁直观,代码简单易懂,但可能受到递归深度的限制。
- 非递归解法:避免了递归栈的开销,适合树的深度较大时使用。
无论是递归还是非递归解法,关键点在于:每次将当前节点的左右子树交换,然后继续对其子节点进行相同操作。两种方法都能高效地解决二叉树的翻转问题。