Day58:对称的二叉树

时间:2022-07-24
本文章向大家介绍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