题目:请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路:何为对称树,所谓对称是指以根结点为界的左右子树左右对称。
方法一:思路很简单,对于先序遍历或者中序遍历或者后序遍历,例如先序遍历(中-左-右),再写一个对称的先序遍历算法(中-右-左)然后分别遍历二叉树,将其放入到2个集合中,然后进行逐一比较即可。需要注意的是,对于二叉树上为null的结点也要遍历并放入到集合中,否则有可能数值相同但是不对称的情况(当所有结点的值相同时)。这种方法很简单,但是需要遍历所有的结点,即使一开始的结点就不对称也需要遍历全部全部的结点,效率较低,需要改进。
方法二:要判断二叉树root是否对称,就看其左右子树root.left和root.right之间是否对称。首先left和right结点的val要相同②,否则不对称;然后left的左子树③要与right的右子树③对称,并且left的右子树④要与right的左子树④对称;于是问题转化为left的左子树③要与right的右子树③对称,并且left的右子树④要与right的左子树④对称。而要判断left的左子树③与right的右子树③是否对称与初始的问题:判断left子树②与right子树②是否对称是相同的原理。即问题总是判断2棵子树是否对称:而要判断2棵子树是否对称的逻辑都是一样的,就是判断这2个子树的根结点值是否相同&&left的左子树与right的右子树是否相同&&left的右子树与right的左子树是否相同。即给定2棵树就可以判断其是否对称,不需要管这2棵树是否是相连于同一个结点(例如结点②和结点②都相连于①)或者是相互远离的(例如结点③和结点③相互远离)。显然判断一棵树是否对称即判断它的2棵子树是否对称,而判断2棵子树left和right是否对称依赖于判断left.left和right.right是否对称并且left.right和right.left是否对称。设计一个递归方法,该方法用于输入2个树的根结点,然后判断这2棵树是否对称并返回true和false.
递推关系:if(process(left.left,right.right)==true&&process(left.right,right.left)==true){returntrue;}
边界条件:
if(left==null&&right!=null)returnfalse;
if(right==null&&left!=null)returnfalse;
if(left==null&&right==null)returntrue;
if(left.val!=right.val)returnfalse;
这个递归非常巧妙,并不是基于后序遍历的改造而是一个全新的逻辑,但是都是利用了初始条件+递推关系的方式来解决问题,对于递归,需要多看多理解多练习多感悟。//判断一棵树是否对称:即判断2棵子树是否对称,递归:判断2组共4棵树是否对称
巧妙:
publicclass Solution {
boolean isSymmetrical(TreeNode pRoot){
//特殊输入
if(pRoot==null) return true;
//调用方法解决问题
return this.process(pRoot.left,pRoot.right);
}
//建立一个递归的方法:输入一个根结点,判断这棵子树是否对称
private boolean process(TreeNodeleftTree,TreeNode rightTree){
//边界条件
if(leftTree==null) returnrightTree==null;
if(rightTree==null) returnleftTree==null;
//如果2子树不为null,那么先看值是否相同
if(leftTree.val!=rightTree.val) returnfalse;
//此时2个子树的值相同,判断这2棵树是否对称依赖于判断它的4棵子树是否满足2组对称条件
booleanres1=process(leftTree.left,rightTree.right);
booleanres2=process(leftTree.right,rightTree.left);
return res1&&res2;
}
}