热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java详解剑指offer面试题27对称的二叉树

Java详解剑指offer面试题27–对称的二叉树请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的ÿ
Java详解剑指offer面试题27–对称的二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

对称的二叉树,结点数必然是奇数,特别地定义空树也是对称的。当对称树的结点值不是完全相同时比较好处理,但是当结点值全部一样时候可能会有些麻烦。我们要实现一个通用的算法,使得对于这种特殊情况也能正确处理。

要保证树是对称的,左子树最左边的结点要和右子树最右边的结点值相同…左子树的右子结点要和右子树的左子结点值相同,即

root1.left == root2.right;
root1.right == root2.left;

这是关键,理解了上面说的,可以很轻松地写出下面的代码。

递归版本

先来看递归版本,递归的实现一般比较简单、清晰。

package Chap4;import java.util.LinkedList;
import java.util.Queue;public class SymmetricalTree {public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}/*** 递归实现*/public boolean isSymmetricalRecur(TreeNode pRoot) {if (pRoot == null) return true;return isSymmetrical(pRoot.left, pRoot.right);}private boolean isSymmetrical(TreeNode root1, TreeNode root2) {if (root1 == null && root2 == null) return true;if (root1 == null || root2 == null) return false;if (root1.val != root2.val) return false;return isSymmetrical(root1.left, root2.right)&& isSymmetrical(root1.right, root2.left);}
}

如果遇到两棵子树都为空流返回true,这句代码隐含了**“空树也是对称的”**这样的信息。否则,只有一子树为空另一不为空,显然不是对称的;如果两个子树都不为空,比较它俩根结点的值,不相同肯定不是对称的。之后递归地对树的子树进行上述判断,直到检查到叶子结点,如果都满足就返回true。

非递归版本

思路和上面一样,非递归实现需要用到两个队列。队列A专门存入左子树,队列B专门存入右子树。

入列时,将左子树的左子结点和右子树的右子结点分别存入队列A和队列B,紧接着还要将左子树的右子结点和右子树的左子结点分别存入队列A和队列B。

出列时,两个队列同时出列一个元素,根据存入的顺序,这两个出列元素就是左子树的左子结点和右子树的右子结点,或者左子树的右子结点和右子树的左子结点。之后对这两个元素进行比较,比较操作和上面递归版本的一样。

package Chap4;import java.util.LinkedList;
import java.util.Queue;public class SymmetricalTree {/*** 非递归&#xff0c;队列实现(栈也可以实现)*/public boolean isSymmetrical(TreeNode pRoot) {if (pRoot &#61;&#61; null) return true;Queue<TreeNode> queueA &#61; new LinkedList<>();Queue<TreeNode> queueB &#61; new LinkedList<>();queueA.offer(pRoot.left);queueB.offer(pRoot.right);TreeNode left &#61; null;TreeNode right &#61; null;while (!queueA.isEmpty() && !queueB.isEmpty()) {left &#61; queueA.poll();right &#61; queueB.poll();// 两个都空跳过if (left &#61;&#61; null && right &#61;&#61; null) continue;// 只有一个空&#xff0c;不对称if (left &#61;&#61; null || right &#61;&#61; null) return false;// 两个都不空&#xff0c;比较值if (left.val !&#61; right.val) return false;// 两两对称的加入// 左孩子的左孩子&#xff0c;右孩子的右孩子queueA.offer(left.left);queueB.offer(right.right);// 左孩子的右孩子&#xff0c;右孩子的左孩子queueA.offer(left.right);queueB.offer(right.left);}return true;}
}


本文参考文献&#xff1a;
[1]github.com/haiyusun/data-structures


推荐阅读
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • Java编程实现邻接矩阵表示稠密图的方法及实现类介绍
    本文介绍了Java编程如何实现邻接矩阵表示稠密图的方法,通过一个名为AMWGraph.java的类来构造邻接矩阵表示的图,并提供了插入结点、插入边、获取邻接结点等功能。通过使用二维数组来表示结点之间的关系,并通过元素的值来表示权值的大小,实现了稠密图的表示和操作。对于对稠密图的表示和操作感兴趣的读者可以参考本文。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • 本文介绍了一道经典的状态压缩题目——关灯问题2,并提供了解决该问题的算法思路。通过使用二进制表示灯的状态,并枚举所有可能的状态,可以求解出最少按按钮的次数,从而将所有灯关掉。本文还对状压和位运算进行了解释,并指出了该方法的适用性和局限性。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
author-avatar
美食和旅丶行_379
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有