题目描述
请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
刚开始的思路:由于题目中说如果与其镜像二叉树相同,那么就是对称的,那我就先建立该二叉树的镜像二叉树,然后比较这两颗二叉树是否一样。
建立镜像二叉树,需要先建立根结点,因为根结点肯定都是一致的,然后递归建立当前结点的左右孩子结点,在建立时将其左右孩子交换,
比较镜像二叉树与当前二叉树:刚开始主要是在递归结束条件处没有思路,应该是两个节点都为空返回true,有一个结点不为空就要返回false,如果两个节点都不为空,那么比较两者的值,如果不相等返回false,如果相等接着向下比较。
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: bool isSymmetrical(TreeNode* pRoot) { if(!pRoot) return true; TreeNode* mirrorRoot = new TreeNode(pRoot->val); mirrorTree(pRoot,mirrorRoot); bool flag=true; isSymmetrical2(pRoot,mirrorRoot,flag); return flag; } void mirrorTree(TreeNode* pRoot,TreeNode* mirrorRoot){ if(pRoot){ TreeNode* mirrorLeft = NULL; TreeNode* mirrorRight = NULL; if(pRoot->right){ mirrorLeft = new TreeNode(pRoot->right->val); } if(pRoot->left){ mirrorRight = new TreeNode(pRoot->left->val); } mirrorRoot->left = mirrorLeft; mirrorRoot->right = mirrorRight; mirrorTree(pRoot->left,mirrorRoot->right); mirrorTree(pRoot->right,mirrorRoot->left); } } void isSymmetrical2(TreeNode* pRoot,TreeNode* mirrorRoot,bool &flag){ if(pRoot&&!mirrorRoot || !pRoot&&mirrorRoot) flag = false; if(flag&&pRoot&&mirrorRoot){ if(pRoot->val!=mirrorRoot->val) flag = false; else flag = true; isSymmetrical2(pRoot->left,mirrorRoot->left,flag); isSymmetrical2(pRoot->right,mirrorRoot->right,flag); } } };
后来,我发现根本不需要建立镜像二叉树就可以得出结果,只需要return isSymmetrical(pRoot->left,mirrorRoot->right)&&isSymmetrical(pRoot->right,mirrorRoot->left)左子树节点和右子树节点进行比较,右子树节点和左子树节点进行比较,这样的话,减少了空间的使用但是增加了时间的消耗。
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: bool isSymmetrical(TreeNode* pRoot) { if(!pRoot) return true; return isSymmetrical(pRoot->left,pRoot->right); } bool isSymmetrical(TreeNode* pRoot,TreeNode* mirrorRoot){ if(!pRoot && mirrorRoot || pRoot&&!mirrorRoot) return false; if(!pRoot&&!mirrorRoot) return true; if(pRoot->val!=mirrorRoot->val) return false; return isSymmetrical(pRoot->left,mirrorRoot->right)&&isSymmetrical(pRoot->right,mirrorRoot->left); } };
接着,我又使用了java实现了它的非递归算法,我的思路是,层次遍历,一层一层遍历,将每一层的值放到队列和栈中,然后依次出队列,出栈(即判断是否是回文),但是这种情况只在满二叉树可用,需要在层次遍历的时候遇到空节点的时候,在栈和队列中弹入-1,即可实现该问题。
import java.util.Queue; import java.util.LinkedList; import java.util.Stack; public class Solution { boolean isSymmetrical(TreeNode pRoot) { if(pRoot == null) return true; Queue<TreeNode> queueRoot = new LinkedList<>(); Queue<Integer> queueOrder = new LinkedList<>(); Stack<Integer> stackReverse = new Stack<>(); TreeNode q; int qSize = 0; queueRoot.add(pRoot); while(!queueRoot.isEmpty()){ qSize = queueRoot.size(); //一层一层遍历 for(int i=0;i<qSize;i++){ q = queueRoot.poll(); if(q == null){//如果是空,那么就将-1入栈入队列 queueOrder.add(-1); stackReverse.push(-1); }else{ queueOrder.add(q.val); stackReverse.push(q.val); queueRoot.add(q.left); queueRoot.add(q.right); } } //判断这层的数据是不是回文 while(!queueOrder.isEmpty() && !stackReverse.empty()){ if(queueOrder.peek() != stackReverse.peek()) return false; queueOrder.poll(); stackReverse.pop(); } } return true; } }
接着,我又在评论区看了其他大神的思路,得到了对于非递归遍历更加简便的方法,其实就是一个从左往右入队列遍历,一个从右往左入队列遍历,然后进行判断,判断的方法与递归的判断条件一致。
import java.util.Queue; import java.util.LinkedList; public class Solution { boolean isSymmetrical(TreeNode pRoot) { if(pRoot == null) return true; Queue<TreeNode> queueOrder = new LinkedList<>(); Queue<TreeNode> queueReverse = new LinkedList<>();
//这里改成了将左子树根节点和右子树根节点分别入队列,因为如果是对称的话,其左右子树应该是对称的
queueOrder.add(pRoot.left);
queueReverse.add(pRoot.right);
TreeNode q1; TreeNode q2; while(!queueOrder.isEmpty() && !queueReverse.isEmpty()){ q1 = queueOrder.poll(); q2 = queueReverse.poll(); if(q1 == null && q2 == null) continue; if(q1 == null || q2 == null) return false; if(q1.val != q2.val) return false; queueOrder.add(q1.left); queueOrder.add(q1.right); queueReverse.add(q2.right); queueReverse.add(q2.left); } return true; } }