原题链接
题目描述
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
方法
思路 01 - 递归
- 前序遍历使用递归实现,按照根左右遍历所有节点
- 翻转所有非叶子节点子节点
- 递归返回条件: 节点为空
代码
class Solution {
/*
* 前序遍历:
* 递归终止条件: 节点为空
*/
public TreeNode invertTree(TreeNode root) {
// 检查输入
if (root == null || (root.left == null && root.right == null)) {
return root;
}
preOrderReverse(root);
return root;
}
public void preOrderReverse(TreeNode node) {
if (node == null) // 叶子节点的子节点为空
return;
swap(node); // 翻转所有非叶子节点子节点
preOrderReverse(node.left); // 左
preOrderReverse(node.right); // 右
}
private void swap(TreeNode node) {
if (node.left == null && node.right == null)
return;
TreeNode tmp = node.left;
node.left = node.right;
node.right = tmp;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(N)
思路 02 - 辅助栈
- 使用栈进行层次遍历,并交换每个子树的左右子节点。
- 如果根节点非空,将其压入栈中。
- 依次将非空的左、右子节点压入栈中以继续遍历。
- 利用临时变量暂存节点信息,实现左右子节点值的互换。
代码
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if (null == root)
return null;
// 借助栈实现遍历树的各个叶子结点
Deque<TreeNode> stack = new LinkedList<>();
stack.push(root); // 记录根节点
while (!stack.isEmpty()) {
TreeNode top = stack.pop(); // 积累当前结点的左右子节点
if (top.left != null)
stack.push(top.left);
if (top.right != null)
stack.push(top.right);
TreeNode tmp = top.left; //更新当前结点的左右节点值
top.left = top.right;
top.right = tmp;
}
return root;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(N)
思路 02 - 广度优先
- 借助队列,如果出队节点左右节点不为空;将其入队
- 每个出队节点交换左右指针
代码
class Solution {
public TreeNode invertTree(TreeNode root) {
// 检查输入 - 如果树节点为空
if (root == null || root.left == null && root.right == null) {
return root;
}
// 层序遍历,借助队
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode peek = queue.poll();
swap(peek);
// 如果左右节点不为空,将其入队
if (peek.left != null)
queue.offer(peek.left);
if (peek.right != null)
queue.offer(peek.right);
}
return root;
}
// 交换左右节点
public void swap(TreeNode node) {
TreeNode tmp = node.left;
node.left = node.right;
node.right = tmp;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(N)