网站首页 > 技术文章 正文
大家好,我是前端西瓜哥。今天做一道比较基础的二叉树算法题。
题目
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
本题 LeetCode 对应地址:
https://leetcode-cn.com/problems/symmetric-tree/
解法
如果你熟练写二叉树的先序、中序、后序遍历的递归写法套路,再看这题,可能一时不太能想到思路。
我一开始做这道题就是这样,我会将注意力放在一个节点上,尝试在上面写出花来。
但对这题来说并不受用,一开始或许可以对比根节点的左右子节点,但左右子节点的后继的子节点就不好取出来对比了。
对于这题,我们需要给递归函数,传入两个节点。
function isSymmetric(root) {
if (!root) return true;
return compare(root.left, root.right);
};
function compare(left, right) {
if (!left && !right) return true;
if (!left || !right) return false;
return left.val === right.val &&
compare(left.left, right.right) &&
compare(left.right, right.left);
}
compare 递归函数接收两个节点,如果这两个节点对称,返回 true,否则返回 false。
首先是 left 和 right 都为 null 的情况,属于对称,返回 null。
null 的情况需要在最前方判断,因为后面我们要使用 left.val 的语法,如果 left 是 null,会报错。
然后就是 left 或 right 其中一个为 null 另一个不为 null 的情况。
因为前面的 if (!left && !right) return true; 如果不符合条件,代码往后走时,left 和 right 至少有一个不为 null。所以只要有 left 或 right 有一个 null,就说明一个为 null 一个不为 null,说明不对称,返回 false。
if (!left && !right) return true;
// 代码能运行到这里,说明 left 和 right 至少有一个为 null
if (!left || !right) return false;
如果你想更容易理解,可以改成这样子:
if (!left && !right) return true;
// 下面代码没有利用上面的条件判断
if (left && !right) return false;
if (!left && right) return false;
最后 left 和 right 都不为 null 的情况,我们需要对比以下节点
- left 和 right
- left.left 和 right.right
- left.right 和 right.left
当这些都为 true 的话,递归函数就返回 true;否则返回 false。
这里的 && 操作符支持短路运行,当前面的条件不符合,后面的函数就不会执行,起到剪枝的效果。
LeetCode 官方递归解法的缺陷
我看了一下 LeetCode 的官方解法,发现它有个地方和我的不一样:
function isSymmetric(root) {
return compare(root, root);
};
function compare(left, right) {
// 实现同上
}
就是它是直接将 root 和 root 对比,我初一看,觉得挺优雅的,不需要像我一样写额外的 root 为空的判断。
但我很快发现了不妥的地方,那就是这种写法,在二叉树是对称的情况下,所有节点都要被访问两次。
虽然从时间复杂度上来说,它也是 O(n) 的量级,但从实际情况是,LeetCode 官方解法在二叉树对称情况下,花费的时间为我的解法的两倍。
如果二叉树不对称,因为 && 运算的短路特性,耗时倒和我的解法没有太大区别。
我是前端西瓜哥,分享前端和算法知识,欢迎关注我。
猜你喜欢
- 2025-06-09 平面几何算法:求点到直线和圆的最近点
- 2025-06-09 解决雪花算法生成的ID传到前端后精度丢失问题
- 2025-06-09 什么是非对称加密算法?(什么是非对称加密,有哪些特点)
- 2025-06-09 React18的diff算法(react-diff-view)
- 2025-06-09 经典监督式学习算法 - 决策树(决策监督制度)
- 2025-06-09 「西瓜哥说算法」从前序与中序遍历序列构造二叉树
- 2024-09-29 前端算法面试题 前端面试题csdn
- 2024-09-29 每天一道算法题——最长连续递增序列
- 2024-09-29 高级前端开发带你搞懂vue的diff算法
- 2024-09-29 前端知识杂记(diff算法自解) diff算法 react
你 发表评论:
欢迎- 503℃几个Oracle空值处理函数 oracle处理null值的函数
- 500℃Oracle分析函数之Lag和Lead()使用
- 496℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 491℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 483℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 474℃【数据统计分析】详解Oracle分组函数之CUBE
- 457℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 455℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)