题目描述
翻转一棵二叉树。
示例:
输入:
4
/ \
2 7
/ \ / \
1 3 6 9
输出:
4
/ \
7 2
/ \ / \
9 6 3 1
备注: 这个问题是受到 Max Howell 的 原问题 启发的 :
谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/in… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
一位大佬吐槽自己面试谷歌因为没写出翻转二叉树被拒了
知识回顾:
前序、中序、后序遍历概念
以根节点作为参考:
-
DLR--前序遍历(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 )
-
LDR--中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)
-
LRD--后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)
解题思路
思路1:广度优先遍历 BFS
- 利用队列的先进先出的原则,进行元素互换;
- 初始化队列:queue=[root]
- 取出最先入队的元素;
- 如果当前节点为null,则进行下一个节点的遍历;
- 否则进行左右子树的交换;
- 交换结束,从左往右继续进行入队;
- 广度优先遍历完成,则当前树完成所有的交互翻转;
代码
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function invertTree(root: TreeNode | null): TreeNode | null {
// 思路1:广度优先遍历:利用队列的先进先出的原则,进行元素互换;
let queue=[root]; // 初始化队列;
while(queue.length>0){
// 取出最先入队的元素;
let current =queue.shift();
if(current===null){
continue;
}
// 当前节点存在,此时进行左右子树互换;
[current.left,current.right]=[current.right,current.left]
//互换结束,从左往右继续进行入队;
queue.push(current.left);
queue.push(current.right)
}// end of queue 直到所有的元素广度优先遍历完毕;
return root;
};
思路2:利用栈stack的特性
- 同理如上
- 可以利用栈stack数据结构的先进后出的原则;
function invertTree(root: TreeNode | null): TreeNode | null {
// 同理可以利用栈stack数据结构的先进后出的原则;
let stack=[root]
while(stack.length>0){
let current=stack.pop();
if(current===null){
continue;
}
//交换左右子树节点;
[current.left,current.right]=[current.right,current.left]
// 栈stack先进出的原则,
stack.push(current.right);
stack.push(current.left);
}// end of stack
return root;
};
思路3:深度优先遍历 DFS
递归:前序遍历
- 前序遍历:
- 先处理根元素,然后再处理左子树,然后再处理右子树;
function invertTree(root: TreeNode | null): TreeNode | null {
// 递归进行前序遍历 :先处理根元素,然后再处理左子树,然后再处理右子树;
if(root===null){
return root;
}
// 进行跟元素交互操作
[root.left,root.right]=[root.right,root.left]
// 处理左子树;
invertTree(root.left);
// 处理右子树
invertTree(root.right);
return root;
};
- 后序遍历:
- 先再处理左子树,然后再处理右子树;最后处理根元素,
function invertTree(root: TreeNode | null): TreeNode | null {
// 递归进行前序遍历 :先处理根元素,然后再处理左子树,然后再处理右子树;
if(root===null){
return root;
}
// 处理左子树;
invertTree(root.left);
// 处理右子树
invertTree(root.right);
// 进行跟元素交互操作
[root.left,root.right]=[root.right,root.left]
return root;
};
二叉树相关回顾
【温故知新】101. 对称二叉树 利用队列、递归实现二叉树的判断
【温故知新】102. 二叉树的层序遍历 广度优先遍历、队列先进先出的原则