遍历问题如果看不懂代码的话,多用示例代入走一圈就会慢慢理解!
前序遍历
给你二叉树的根节点
root,返回它节点值的 前序遍历。
递归
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [1,2,4,5,8,9,3,6,7,10]
思路
熟悉递归的话其实非常简单,就是每个结点都保证按照根左右的顺序就行
- 递归边界:叶子结点
- 递归式: 打印当前结点(root)的值->左子树前序遍历->右子树前序遍历
代码
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var preorderTraversal = function(root) {
var res=new Array();
function preorder(rootnode){
if(!rootnode) return;
res.push(rootnode.val);
preorder(rootnode.left);
preorder(rootnode.right);
}
preorder(root);
return res;
};
迭代
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [1,2,4,5,8,9,3,6,7,10]
思路
前序遍历需要按照根->左->右的顺序遍历,可以利用栈结构来控制输出序列的顺序。 观察示例:
- 根结点出栈后左右儿子才出栈
- 左子树比右子树先出栈
- 获取到根结点才能获取到左右儿子 结合栈后进先出的特点,我们应该
- 顺序:根结点出栈->右子树入栈->左子树入栈
- 每个结点出栈时,将其对应的值push到结果数组中
代码
var preorderTraversal = function(root) {
if(root===null) return [];
const res=[];
const stack=[];
stack.push(root);
while(stack.length>0){
const temp=stack.pop();
res.push(temp.val);
if(temp.right) stack.push(temp.right);
if(temp.left) stack.push(temp.left);
}
return res;
};
后序遍历
给你一棵二叉树的根节点
root,返回其节点值的 后序遍历 。
递归
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [4,8,9,5,2,6,10,7,3,1]
思路
跟前序一样,只是顺序变为左右根。
代码
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var postorderTraversal = function(root) {
const res=[];
const postorder=function(root){
if(!root) return ;
postorder(root.left);
postorder(root.right);
res.push(root.val);
}
postorder(root);
return res;
};
迭代
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [4,8,9,5,2,6,10,7,3,1]
思路
后序遍历需要按照左->右->根的顺序遍历,同样尝试用栈结构处理。 观察示例:
- 结果数组中左右儿子在根结点的前面
- 左子树比右子树先出栈
- 获取到根结点才能获取到左右儿子->根结点先入出栈
第一点和第三点要使得先从栈中取出来的根最后放入结果中,换一个角度想就是结果数组中根结点在左右子树的右边,js里就可以使用
unshift()嘛!(记得左右子树入栈的顺序也要反一反)
代码
var postorderTraversal = function(root) {
const res=[];
if(!root) return res;//边界处理
const stack=[];
stack.push(root);
while(stack.length){
const temp=stack.pop();
if(temp.left) stack.push(temp.left);
if(temp.right) stack.push(temp.right);
res.unshift(temp.val);
}
return res;
};
中序遍历
给定一个二叉树的根节点
root,返回它的 中序 遍历
递归
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [4,2,8,5,9,1,6,3,7,10]
代码
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var inorderTraversal = function(root) {
const res=[];
const inorder=function(root){
if(!root) return;
inorder(root.left);
res.push(root.val);
inorder(root.right);
}
inorder(root);
return res;
};
迭代
示例
输入: root = [1,2,3,4,5,6,7,null,null,8,9,null,null,null,10]
输出: [4,2,8,5,9,1,6,3,7,10]
思路
中序遍历的顺序是左->根->右,左右子树在根的不同方向,不能用前两种遍历的基本思路:获取根再获取左右子树来做。
- 需要先定位到最左边的结点:④ 路径为①-②-④
- 将上述路径记录下来,回溯时便可到达④的父节点 ②
- 从父结点点②即可获取④的兄弟结点,从而完成左根右的遍历顺序。
代码
var inorderTraversal = function(root) {
const res=[];//结果数组
const stack=[];//辅助栈
let curr=root;//游标
while(stack.length||curr){
while(curr){
stack.push(curr);
curr=curr.left;//找到最左的叶子结点,把途径的结点都记录下来
}
curr=stack.pop();
res.push(curr.val);
curr=curr.right;//查看当前cur结点的右孩子
}
return res;
};
层序遍历
从上到下
给你二叉树的根节点
root,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。【力扣102】
示例
输入: root = [3,9,20,null,null,15,7]
输出: [[3],[9,20],[15,7]]
思路
层序遍历很显然是先进先出,用队列来完成。需要注意的是每次循环时队列的长度就是当前层次的结点数。
代码
var levelOrder = function(root) {
if(!root) return [];
const queue=[];
const res=[];
queue.push(root);
while(queue.length){
let levelLength=queue.length;//当前层的结点数
let levelVal=[];//用于存放当前层的结点值
for(let i=0;i<levelLength;i++){//遍历当前层
let temp=queue[0];//队头 即当前遍历到的结点
levelVal.push(temp.val);
if(temp.left) queue.push(temp.left);//将结点的左右子结点入队
if(temp.right) queue.push(temp.right);
queue.shift();// 将已遍历结点出队
}
res.push(levelVal);//当前层遍历完后放入结果,继续遍历下一层
}
return res;
};
从下到上
给你二叉树的根节点
root,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)【力扣107】
示例
输入: root = [3,9,20,null,null,15,7]
输出: [[15,7],[9,20],[3]]
思路
参考后序遍历的思路就很简单!
代码
var levelOrderBottom = function(root) {
const res=[];
const queue=[];
if(!root) return res;
queue.push(root);
while(queue.length){
const len=queue.length;
const levelRes=[];
for(let i=0;i<len;i++){
let temp=queue.shift();
levelRes.push(temp.val);
if(temp.left) queue.push(temp.left);
if(temp.right) queue.push(temp.right);
}
res.unshift(levelRes);
}
return res;
};