welcome to my blog
剑指offer面试题28(java版):对称的二叉树
题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路
- 自定义后序遍历:根右左
- 在考虑叶子节点的left和right的情况下(也就是考虑null), 如果前序遍历和后序遍历的结果相同, 那么二叉树是对称的
小心短路!!!
if(s1.pop()==null && s2.pop()==null)
continue;
第三次做, 从同一个节点开始进行两种遍历, 每一轮递归中检查两种遍历经过的节点的情况(null与val)
/*
从根节点开始, 进行镜像的遍历, 每一轮都比较val是否相等
*/
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;
return Core(pRoot.left, pRoot.right);
}
boolean Core(TreeNode root1, TreeNode root2){
if(root1==null && root2==null)
return true;
if((root1==null&&root2!=null) || (root1!=null&&root2==null))
return false;
if(root1.val!=root2.val)
return false;
//here, root1.val == root2.val
//左右子树也得是镜像的
return Core(root1.left, root2.right) && Core(root1.right, root2.left);
}
}
第二次做; 核心:一棵树,递归中采用两种遍历方式
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;//和面试官商量
return Core(pRoot, pRoot);
}
//一棵树用两种遍历方式去遍历
boolean Core(TreeNode root1, TreeNode root2){
//base case
if(root1==null && root2==null)
return true;
if((root1==null&&root2!=null) || (root1!=null&&root2==null))
return false;
//
if(root1.val == root2.val)//根
//一个是根左右的遍历, 另一个是根右左的遍历
return Core(root1.left, root2.right) && Core(root1.right, root2.left);
return false;
}
}
第二次做, 做的有点麻烦; 必须要考虑结构信息,其实就是要考虑null,所以压栈的时候,是null就要压入null; 需要改进方法, 在一个递归中完成任务
/*
借助两个栈, 正常压入和镜像压入栈
弹出并比较
*/
import java.util.Stack;
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;//问问面试官这个返回什么
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
leftStack(s1, pRoot.left);
rightStack(s2, pRoot.right);
while(!s1.isEmpty() && !s2.isEmpty()){
TreeNode n1 = s1.pop(), n2 = s2.pop();
if(n1==null && n2 ==null)
continue;
if((n1==null&&n2!=null) || (n1!=null&&n2==null))
return false;
if(n1.val != n2.val)
return false;
}
return s1.isEmpty()&&s2.isEmpty();
}
void leftStack(Stack<TreeNode> s, TreeNode root){
if(root==null){
s.push(null);
return;
}
s.push(root);
leftStack(s, root.left);
leftStack(s, root.right);
}
void rightStack(Stack<TreeNode> s, TreeNode root){
if(root==null){
s.push(null);
return;
}
s.push(root);
rightStack(s, root.right);
rightStack(s, root.left);
}
}
public class Solution {
public boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;
return isSymmetricalCore(pRoot, pRoot);
}
public boolean isSymmetricalCore(TreeNode root1, TreeNode root2){
// recursion finish
if(root1 == null && root2 == null)
return true;
if(root1 == null && root2 != null)
return false;
if(root1 != null && root2 == null)
return false;
if(root1.val != root2.val)
return false;
return isSymmetricalCore(root1.left, root2.right) && isSymmetricalCore(root1.right, root2.left);
}
}
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
稍加改进后的代码(减少了判断语句)
虽然上面的代码相对长一些, 但是一定意义上说逻辑更加清晰
public class Solution {
public boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;
return isSymmetricalCore(pRoot, pRoot);
}
public boolean isSymmetricalCore(TreeNode root1, TreeNode root2){
// recursion finish
if(root1 == null && root2 == null)
return true;
if(root1 != null && root2 != null && root1.val == root2.val)
return isSymmetricalCore(root1.left, root2.right) && isSymmetricalCore(root1.right, root2.left);
return false;
}
}