Day58:对称的二叉树
剑指Offer_编程题——对称的二叉树
题目描述:
请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
具体要求:
时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M
具体实现:
思路一: 根据本题对二叉树的对称性的定义可知:如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。因此,我们首先要找出二叉树的镜像,其实这个在我们之前的文章中做过这么一道题目。只要用其中的递归方法找到该二叉树的镜像,然后再通过交换左右子树将其二叉树对称实现,这里需要注意的是:空子树的情况我们也要考虑。具体用java实现如下:
public class Solution{
boolean isSymmetrical(TreeNode pRoot){
TreeNode node = getMirror(pRoot);
return isSymmetrical(pRoot, node);
}
boolean isSymmetrical(TreeNode pRoot, TreeNode node){
if(pRoot == null && node == null)
return true;
else if(pRoot == null || node == null)
return false;
if(pRoot.val == node.val)
return isSymmetrical(pRoot.left, node.left) && isSymmetrical(pRoot.right, node.right);
return false;
}
TreeNode getMirror(TreeNode pRoot){
if(pRoot == null){
return null;
}
TreeNode root = new TreeNode(pRoot.val);
root.right = getMirror(pRoot.left);
root.left = getMirror(pRoot.right);
return root;
}
}
代码效果图如图所示:
正如前面说的那样,如果在牛客网中,我们可以直接通过,但是如果是本地的编译器,则还需要定义其结点,具体结点的实现定义用java实现如下:
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
TreeNode next = null;
TreeNode(int val) {
this.val = val;
}
}
思路二: 首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同,左子树的右子树和右子树的左子树相同即可,采用递归,另外非递归也可,采用栈或队列存取各级子树根节点。若果二叉树结点值相同,但是不对称,上述方法结果不对,故需要比较空结点位置是不是相同。具体我们用java和python两种编程语言将其实现: 1、首先我们用java将其实现:
public class Solution{
boolean isSymmetrical(TreeNode pRoot){
if(pRoot == null)
return true;
return isSymmetrical(pRoot.left, pRoot.right);
}
private boolean isSymmetrical(TreeNode left, TreeNode right){
if(left == null && right == null)
return true;
if(left == null || right == null)
return false;
if(left.val == right.val)
return isSymmetrical(left.left, right.right) && isSymmetrical(left.right, right.left);
return false;
}
}
代码效果图如图所示:
2、接下来我们用Python将其实现:
class Solution:
def isSymmetrical(self, pRoot):
return self.is_Symmetrical(pRoot, pRoot)
def is_Symmetrical(self, p, q):
if p == None and q == None:
return True
if p == None or q == None:
return False
if p.val != q.val:
return False
return self.is_Symmetrical(p.left, q.right) and self.is_Symmetrical(p.right, q.left)
代码效果图如图所示:
但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用python定义链表结构实现如下:
class TreeNode:
def __init__(self, pNode):
self.val = x
self.left = None
self.right = None
思路三: 其实与思路二差不多,就是在思路二的基础上进行了简单的改造。当我门对所有空的情况考虑结束之后,我们应该考虑当对称结点不相等,认为错误。对称结点相等,考虑它们的下一层结点,注意(右结点的右孩子——左结点的左孩子,右结点的左孩子——左结点的右孩子)。具体我们分别用java和python两种语言将其实现: 1、首先我们用java将其实现:
public class Solution{
boolean isSymmetrical(TreeNode pRoot){
if(pRoot == null)
return true;
return help(pRoot.left, pRoot.right);
}
boolean help(TreeNode node1, TreeNode node2){
if(node1 == null && node2 == null)
return true;
if(node1==null && node2!=null)
return false;
if(node1!=null && node2==null)
return false;
if(node1.val!=node2.val)
return false;
return help(node1.left, node2.right)&&help(node1.right, node2.left);
}
}
代码效果图如图所示:
2、接下来我们用python将其实现:
class Solution:
def isSymmetrical(self, pRoot):
head = pRoot
if head == None:
return True
if head.left == None and head.right == None:
return True
return self.judge(head.left, head.right)
def judge(self, right, left):
if right == None and left == None:
return True
if right == None or left == None:
return False
if right.val != left.val:
return False
return self.judge(right.right, left.left) and self.judge(right.left, left.right)
代码效果图如图所示:
思路四: 给定一个二叉树,检查它是否是镜像对称的。例如,二叉树[1,2,2,3,4,4,3]就是对称的。具体该二叉树如下图所示:
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
因此,我们可以利用容器队列先入先出,其实容器的选择没有影响,借用两个容器,存储左右子节点的值,不论是队列还是栈,先入先出或者先入后出,只要出来的数字相等就可以。不过这里我们选择java中的LinkedList容器。前面我们介绍了递归的解法。现在我们给大家用Java实现迭代。具体实现如下:
import java.util.Stack;
public class Solution {
boolean isSymmetrical(TreeNode pRoot) {
if(pRoot == null)
return true;
Stack<TreeNode> s = new Stack<TreeNode>();
s.push(pRoot.left);
s.push(pRoot.right);
while(!s.isEmpty()){
TreeNode right = s.pop();
TreeNode left = s.pop();
if(right == null && left == null)
continue;
if(right == null || left == null)
return false;
if(right.val != left.val)
return false;
s.push(left.left);
s.push(right.right);
s.push(left.right);
s.push(right.left);
}
return true;
}
}
代码效果图如图所示:
总结
本题主要通过二叉树的对称来考察二叉树遍历中的层次遍历。前面有一道二叉树的镜像与本题考察的内容相似,只不过本题在此基础上进行了延续,要考虑其子树为空的情况。本文给出了四种解题思路,并且分别用java和python两种主要的编程语言将其实现。并且用到了我们经常在树中用到的递归以及迭代的思路,在迭代的过程中,我们还用到了栈。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!
参考文献
[1] vivia [2] 悠风号 [3] 明月几时有. [4] yg838457845
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一起来学演化计算-matlab基本函数inf, isempty, round, floor, fix
- 一起来学演化计算-matlab基本函数randperm end数组索引
- 论文研读-基于决策变量聚类的大规模多目标优化进化算法
- 一起来学演化计算-matlab基本函数min
- 一起来学演化计算-matlab基本函数find
- 欧拉图和哈密顿图
- python 操作 txt 文件中数据教程[4]-python 去掉 txt 文件行尾换行
- java字符数组char[]和字符串String之间的转换
- python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件
- python操作txt文件中数据教程[1]-使用python读写txt文件
- python循环删除列表元素常见错误与正确方法
- Python字符串,整型,浮点数相互转化
- python创建与遍历List二维列表
- 论文研读-基于变量分类的动态多目标优化算法
- matplotlib交互模式与pacharm单独Figure设置