准备知识
相关术语
树中每个元素都叫做节点,位于树顶部的节点叫做根节点,没有父节点,节点分祖先节点、后代节点
深度:节点祖先节点的个数
树的高度:最大的节点的深度
二叉搜索树:二叉树的一种,但是左侧子节点值比父节点的值小,右侧子节点的值比父节点的值大
LeetCode上最常用二叉搜索树
注:下列题目使用递归,迭代法待续(2020.05.09)
N叉树的后序遍历
/**
* // Definition for a Node.
* function Node(val,children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node} root
* @return {number[]}
*/
var postorder = function (root) {
let res = [];
const fun = (root) => {
if (root === null) {
return null;
}
for (let i = 0; i < root.children.length; i++) {
fun(root.children[i])
}
res.push(root.val)
}
fun(root);
return res;
};
N叉树的前序遍历
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node} root
* @return {number[]}
*/
var preorder = function(root) {
let res = [];
const fun = (root) =>{
if(root === null){
return null;
}
res.push(root.val)
for(let i = 0;i<root.children.length;i++){
fun(root.children[i])
}
}
fun(root);
return res;
};
前后的不同
在于内部函数里面res.push(root.val)
在递归调用的前面还是后面
二叉树
二叉树的前序遍历(根左右)
var preorderTraversal = function(root) {
const res = []
function traversal (root) {
if (root !== null) {
res.push(root.val) // 访问根节点的值
traversal(root.left) // 递归遍历左子树
traversal(root.right) // 递归遍历右子树
}
}
traversal(root)
return res
}
二叉树的中序遍历(左根右)
var inorderTraversal = function(root) {
const res = []
function traversal (root) {
if (root !== null) {
traversal(root.left)
res.push(root.val)
traversal(root.right)
}
}
traversal(root)
return res
}
二叉树的后序遍历(左右根)
var postorderTraversal = function(root) {
const res = []
function traversal (root) {
if (root !== null) {
traversal(root.left)
traversal(root.right)
res.push(root.val)
}
}
traversal(root)
return res
}
分析
同理,在于res.push(root.val)
在内部函数中的位置,因为本语句访问根节点的值,代表根的位置
相同的树
判断两树是否相同
var isSameTree = function(p, q) {
function traversal (root1, root2) {
if (root1 === null && root2 !== null) {
return false
} else if (root1 !== null && root2 === null) {
return false
} else if (root1 === null && root2 === null) {
return true
} else {
return root1.val === root2.val && traversal(root1.left, root2.left) && traversal(root1.right, root2.right)
}
}
return traversal(p, q)
}
分析
1.有一个空,一个非空,必不相同
2.排除以上情况后,只存在全空,或者全不为空,全空必相同
3.排除以上情况后,只存在全不为空,根节点值不等,必不想等
4.排除以上情况后,返回递归两树的根节点的左子节点 与上 两树根节点的右子节点
翻转二叉树
/**
* 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 {TreeNode}
*/
var invertTree = function(root) {
if(!root){
return null;
}
// 交换
var temp = root.left;
root.left = root.right;
root.right = temp;
// 递归左右节点
invertTree(root.left)
invertTree(root.right)
return root
};
分析
1.如果空,没必要翻转,返回null
2.根节点的左右节点交换(临时变量)
2.递归
二叉树的最大深度
var maxDepth = function(root) {
// 递归向下
// 深度是左右节点最大深度加1
return root? Math.max(maxDepth(root.left),maxDepth(root.right))+1 : 0;
};
分析
一棵树的最大深度是左右子树中深度最大的一方+1(一个根节点)
如果为空,结束递归
N叉树的最大深度
var maxDepth = function (root) {
if (!root) return 0;
let max = 0;
for (let i of root.children) {
max = Math.max(max, maxDepth(i));
}
return max + 1;
};
分析
和二叉树的区别在于要遍历一下根节点的每个子节点,然后取最大的
在一组数中取最大的方法是先将第一个存入max,之后每个和max比较,谁大谁设置为max
最后+1