问题
- 请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
解决
//定义二叉树结构
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
//1、递归
class Solution{
public boolean isSymmetric(TreeNode root){
if(root==null) return true; //如果二叉树为空,则是对称的
return check(root,root);
}
public boolean check(TreeNode r1,TreeNode r2){
if(r1==null&&r2==null) return true;
if(r1==null||r2==null) return false; //这两句是如果r1和r2同时为空则返回true,只有其中一个是空返回false
return r1.val==r2.val&&check(r1.left,r2.right)&&check(r1.right,r2.left); //如果是对称的话,一棵树的左子树总是等于另一颗树右子树
}
}
- 递归的时间复杂度和空间复杂度
//2、迭代(首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法)
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root, root);
}
public boolean check(TreeNode u, TreeNode v) {
Queue<TreeNode> q = new LinkedList<TreeNode>();
q.offer(u); //添加一个元素并返回true,如果已满返回false
q.offer(v);
while (!q.isEmpty()) {
u = q.poll(); //移除并返问队列头部的元素 如果队列为空,则返回null
v = q.poll();
//判断不是对称树的条件
if (u == null && v == null) {
continue;
}
if ((u == null || v == null) || (u.val != v.val)) {
return false;
}
//这里有点难理解,如果是原树是对称的,那么它的每相邻两棵树之间,1树的左孩子等于2树的右孩子,1树的右孩子等于2树的左孩子。
q.offer(u.left);
q.offer(v.right);
q.offer(u.right);
q.offer(v.left);
}
return true;
}
}
- 迭代的时间复杂度和空间复杂度
//3、通过创建镜像,比较原相和镜像是否相同判断二叉树是否对称(特别注意克隆部分,不克隆会导致原相变成镜像)
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null) return true; //如果二叉树为空,则是对称的
//获得二叉树的镜像
TreeNode curroot=cloneTree(root);
TreeNode newroot=isSymmetricCopy(curroot);
return check(root,newroot);
}
public TreeNode isSymmetricCopy(TreeNode root){
if(root==null) return root;
TreeNode left=isSymmetricCopy(root.left); //获得左子树的镜像
TreeNode right=isSymmetricCopy(root.right); //获得右子树的镜像
root.left=right; //简化右子树的镜像作为左子树
root.right=left; //简化右子树的镜像作为右子树
return root;
}
public boolean check(TreeNode root,TreeNode newroot){ //无法比较,因为root和newroot是同一个树
if (root == null && newroot == null) {
return true;
}
if (root == null || newroot == null) {
return false;
}
return check(root.left,newroot.left)&&check(root.right,newroot.right)&&root.val==newroot.val;
}
public TreeNode cloneTree(TreeNode root){
TreeNode node=null;
if(root==null) return null;
node=new TreeNode(root.val);
node.left=cloneTree(root.left);
node.right=cloneTree(root.right);
return node;
}
}
- 方法三的时间复杂度和空间复杂度:O(N) O(N),但是常数上有区别
//试错
//4、仅仅根据先序的话还是会出现错误
class Solution{
public boolean isSymmetric(TreeNode root){
if(root==null) return true; //如果二叉树为空,则是对称的
ArrayList r1=new ArrayList<>();
ArrayList r2=new ArrayList<>();
ArrayList l1= preOrderRecur(root,r1);
int size=r1.size();
TreeNode newroot=isSymmetricCopy(root);
ArrayList l2=preOrderRecur(newroot,r2);
for (int i = 0; i < size; i++) {
if (l1.get(i) != l2.get(i)) {
return false;
}
}
return true;
}
//获得二叉树镜像方法
public static TreeNode isSymmetricCopy(TreeNode root){
if(root==null) return root;
TreeNode left=isSymmetricCopy(root.left); //获得左子树的镜像
TreeNode right=isSymmetricCopy(root.right); //获得右子树的镜像
root.left=right; //简化右子树的镜像作为左子树
root.right=left; //简化右子树的镜像作为右子树
return root;
}
//先序遍历二叉树
public static ArrayList preOrderRecur(TreeNode root, ArrayList list) {
if (root == null) {
return list;
}
// System.out.print(root.val+ " ");
list.add(root.val);
preOrderRecur(root.left,list);
preOrderRecur(root.right,list);
return list;
}
}
原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/275946.html