「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
什么是二叉树?
二叉树就是一个树形结构,但是每个节点最多只能有两个子节点,我们一般称之为左右子节点。
树型结构在前端中的应用比比皆是,比如说级联选择器、树型表格等等。可能有小伙伴会有疑惑,我就是个普通的前端工程师,我用的都是普通树结构,需要学二叉树吗?
其实我们学习二叉树,更多的是学习一种使用于标准树结构的解题思路,与分治思想。
老规矩直接用代码说话
第一道题:
226. 翻转二叉树
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var invertTree = function(root) {
return root ? rotateChildren(root) : root;
};
var rotateChildren = function(node) {
if (!node) return ;
let temp = node.left || null;
node.left = node.right || null;
node.right = temp;
rotateChildren(node.left);
rotateChildren(node.right);
return node;
}
代码解析: 旋转一颗树,其实我们可以把它拆成两个步骤:
- 写一个通用的旋转方法,用来旋转某个节点的左右两个节点
- 当节点旋转完毕后,递归调用子节点来进行旋转, 直至最后一层
结合业务: 给属性结构的数据进行排序
某天你可能接收到一个奇怪的需求,有一个你自制的级联选择器的数据是通过后端提供的好几个接口拼接而成的,而领导希望用户在用的时候,这一部分的数据是有序的。
解决方案: 把问题拆成两个步骤
1.写一个通用的排序方法,用来给某个节点的所有子节点排序
2.当前的节点排序完后,递归的调用子节点来进行排序,直至最后一层
多么神奇的事情,这两者的相似度惊人的高。这意味着我们只需要通过函数柯里化把步骤1抽离成一个可以传递的参数,就实现了一个通用的递归方法。
第二道题
剑指 Offer 55 - I. 二叉树的深度
老规矩,拿到树型结构,一律递归梭哈。
/**
* @param {TreeNode} root
* @return {number}
*/
var maxDepth = function(root) {
return root ? findNext([root]) : null;
};
var findNext = function(arr, count = 1) {
let result = [];
arr.forEach(item => {
if (item) {
item.left && result.push(item.left);
item.right && result.push(item.right);
}
});
if (result.length) {
return findNext(result, count + 1);
}
return count;
}
答案解析: 这道题我用了个比较笨的解法, 你不就是想求最多的层数嘛。我就直接把你上一次的的结果统统记录下来,然后下一轮再把这一轮的子节点拿来递归,这是我以前第一次做递归题目时候想到的一个笨方法,相对来说比较容易写出来这种代码。当前也可以使用第一题的解题方法,把这道题的前置条件做成Math.max(左子节点, 右子节点)去递归的判断。
总结:
拿到树形结构要做数据的处理,我一般就是习惯性写个递归方法去梭哈。然而写递归方法有个前提,你要把这个问题抽离成同样问题的统一集合。更多关于二叉树在前端中的应用欢迎小伙伴们在评论区留言。共同进步一起冒泡~!