基础知识
二叉树是一种「数据结构」,是一个包含节点,以及它的左右孩子的一种数据结构。
遍历方式
1
/ \
2 3
/ \ / \
4 5 6 7
如果你按照 根节点 -> 左孩子 -> 右孩子 的方式遍历,即「先序遍历」,每次先遍历根节点,遍历结果为 1 2 4 5 3 6 7;
同理,如果你按照 左孩子 -> 根节点 -> 右孩子 的方式遍历,即「中序序遍历」,遍历结果为 4 2 5 1 6 3 7;
如果你按照 左孩子 -> 右孩子 -> 根节点 的方式遍历,即「后序序遍历」,遍历结果为 4 5 2 6 7 3 1;
最后,层次遍历就是按照每一层从左向右的方式进行遍历,遍历结果为 1 2 3 4 5 6 7。
对于前序、中序和后序遍历,只需将递归函数里的 res.push(node.val)放在不同位置即可,然后调用这个递归函数就可以了,代码完全一样。
1.前序遍历
144.二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。(左节点——根节点——右节点)
示例:
输入:root = [1,2,3,4,5,6,7] 输出:[1,2,4,5,3,6,7]
1
/ \
2 3
/ \ / \
4 5 6 7
解法一:递归
var preorderTraversal = function(root) {
let res = []
const dfs = (node) => {
if(node === null) return
res.push(node.val)
dfs(node.left)
dfs(node.right)
}
dfs(root)
return res
};
解法二:迭代
var preorderTraversal = function(root) {
if(!root) return []
let res = [], stack = [root]
while(stack.length){
let node = stack.pop()
if(node){
res.push(node.val)
if(node.right) stack.push(node.right)//注意stack后进先出,先存入右节点
if(node.left) stack.push(node.left)
}
}
return res
};
写法二:模板
var preorderTraversal = function(root) {
if(!root) return []
let res = [], stack = [root]
while(stack.length){
let node = stack.pop()
if(node){
if(node.right) stack.push(node.right)
if(node.left) stack.push(node.left)
stack.push(node)
stack.push(null)
}else{
res.push(stack.pop().val)
}
}
return res
};
2.中序遍历
94.二叉树的中序遍历
给定一个二叉树的根节点 root ,返回它的 中序 遍历。
示例:
输入:root = [1,2,3,4,5,6,7] 输出:[4,2,5,1,6,3,7]
1
/ \
2 3
/ \ / \
4 5 6 7
解法一:递归
var inorderTraversal = function(root) {
let res = []
const dfs = (node) => {
if(!node) return
dfs(node.left)
res.push(node.val)
dfs(node.right)
}
dfs(root)
return res
};
解法二:迭代
var inorderTraversal = function(root) {
let res = [], stack = [root]
if(!root) return res
while(stack.length){
let node = stack.pop()
if(node){
if(node.right) stack.push(node.right)
stack.push(node)
stack.push(null)
if(node.left) stack.push(node.left)
}else{
res.push(stack.pop().val)
}
}
return res
};
3.后序遍历
145.二叉树的后序遍历
给定一个二叉树,返回它的 后序 遍历。(左节点——右节点——根节点)
示例:
输入:root = [1,2,3,4,5,6,7] 输出:[4,5,2,6,7,3,1]
1
/ \
2 3
/ \ / \
4 5 6 7
解法一:递归
var postorderTraversal = function(root) {
let res = []
const dfs = (node) => {
if(!node) return
dfs(node.left)
dfs(node.right)
res.push(node.val)
}
dfs(root)
return res
};
解法二:迭代
var postorderTraversal = function(root) {
if (!root) return []
let stack = [root], res = []
while (stack.length) {
let node = stack.pop();
if (node !== null) {
stack.push(node);
stack.push(null);
if (node.right) stack.push(node.right)
if (node.left) stack.push(node.left)
} else {
res.push(stack.pop().val);
}
}
return res;
}
4.层序遍历
102.二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层序遍历结果:
[
[3],
[9,20],
[15,7]
]
解法:队列BFS
var levelOrder = function(root) {
let res = [], queue = [root]
if(!root) return res
while(queue.length){
let len = queue.length
let arr = []
while(len--){
let node = queue.shift()
arr.push(node.val)
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
res.push(arr)
}
return res
};
5.锯齿遍历
103.二叉树的锯齿形层序遍历
给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层序遍历如下:
[
[3],
[20,9],
[15,7]
]
解法:队列+标志
var zigzagLevelOrder = function(root) {
let res = [], queue = [root], flag = true
if(!root) return res
while(queue.length){
let len = queue.length
let arr = []
while(len--){
let node = queue.shift()
flag? arr.push(node.val) : arr.unshift(node.val)//翻转方向
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
flag = !flag
res.push(arr)
}
return res
};