除了前中后序,还有层序遍历,在之前的文章里写过,用的BFS+队列。
而对于前中后序遍历,常见的有两种方法:递归和迭代。
144 | 1001 | 68.5% | 中等 |
145 | 882 | 73.5% | 中等 |
94 | 1193 | 74.1% | 中等 |
102 | 1452 | 63.7% | 中等 |
1.前序遍历
①递归:
var preorderTraversal = function(root) {
let res = []
var dfs = function(root) {
if (!root) return;
res.push(root.val);
dfs(root.left);
dfs(root.right);
}
dfs(root);
return res;
};
注意递归的终止条件,最后return;或者return res;都行
对于中序和后序,区别只在于dfs函数内部三行代码的先后顺序。下面来看一下迭代法。
②迭代+栈:
学习于https://www.bilibili.com/video/BV15K4y1Y7Gz?from=search&seid=2301269158871100139
相当于DFS,先搜索完左下角,再逐渐往右搜索。
var preorderTraversal = function(root) {
if(!root) return[];
let res =[];
let stack = [];
while (root || stack.length > 0) {
while(root){
res.push(root.val);
stack.push(root);
root = root.left;
}
let cur = stack.pop();
root = cur.right;
}
return res;
};
注意stack.length > 0这里,不能用stack !== [],js里空数组的判断很怪,之前博客说过。
2.后序遍历
①递归:略
②迭代+栈:
前序是根左右,后序是左右根,相当于根右左.reverse(),所以对调前序遍历的left和right即可。
这样相当于有了模板,很巧妙。
var postorderTraversal = function(root) {
if(!root) return[];
let res =[];
let stack = [];
while (root || stack.length > 0) {
while(root){
res.push(root.val);
stack.push(root);
root = root.right;
}
let cur = stack.pop();
root = cur.left;
}
return res.reverse();
};
3.中序遍历
①递归:略
②迭代+栈:
中序不能完全照搬刚刚的模板,因为前序和后序在刚刚的过程中都相当于进栈的过程中压入res(根左右,根右左.reverse()),而中序时,是左根右,要出栈的时候压入res:
var inorderTraversal = function(root) {
let stack = [];
let res = [];
while(root || stack.length !== 0) {
while(root) {
stack.push(root);
root = root.left;
}
let node = stack.pop();
res.push(node.val);
root = node.right;
}
return res;
};
总结:
这三种遍历的两种方法,递归和迭代,都有模板。
递归三行。
迭代的核心代码只有五行,只需变动位置。