原题
链接:https://leetcode.com/problems/symmetric-tree/
解法概览
本题共有3种解法,解法1为别人的解答,解法2为参考别人思路后改造:https://discuss.leetcode.com/topic/5941/recursive-and-non-recursive-solutions-in-java
解法1:递归法
解法2:迭代法,基于BFS
解法4:迭代法,基于DFS
解法1
解法分析
递归法。
最小的分析单元为1+2+4个节点,对于一个节点来说,如果2个子节点不对称或者4个孙节点不对称,那么该树就不对称;如果对称,需要进一步判断其他的节点,判断顺序为自顶向上。
代码
public class Solution101_recursive {
public boolean isSymmetric(TreeNode root) {
return root == null || isSymmetricHelper(root.left, root.right);
}
private boolean isSymmetricHelper(TreeNode left, TreeNode right) {
if (left == null || right == null)
return left == right;
if (left.val != right.val)
return false;
return isSymmetricHelper(left.left, right.right) && isSymmetricHelper(left.right, right.left);
}
}
解法2
解法分析
迭代法,基于BFS。使用了队列,具体思路与图解类似于LeetCode题解-104-Maximum Depth of Binary Tree,但是不同的是每层节点中是外侧的节点先进队列。
代码
public class Solution101_BFS_iterator {
public boolean isSymmetric(TreeNode root) {
if (root == null)
return true;
TreeNode leftNode, rightNode;
Deque<TreeNode> deque = new LinkedList<TreeNode>();
if (root.left != null){
if (root.right == null)
return false;
deque.push(root.left);
deque.push(root.right);
}
else if (root.right != null)
return false;
while (!deque.isEmpty()){
if (deque.size() % 2 != 0)
return false;
rightNode = deque.pop();
leftNode = deque.pop();
if (rightNode.val != leftNode.val)
return false;
if (leftNode.left != null){
if (rightNode.right == null)
return false;
deque.addLast(leftNode.left);
deque.addLast(rightNode.right);
}
else if (rightNode.right != null)
return false;
if (leftNode.right != null){
if (rightNode.left == null)
return false;
deque.addLast(leftNode.right);
deque.addLast(rightNode.left);
}
else if (rightNode.left != null)
return false;
}
return true;
}
}
解法3
解法分析
同时进行2个后序遍历。
一个迭代器进行标准的后序遍历:1)后序遍历左子树,2)后序遍历右子树,3)访问根节点;
一个迭代器进行镜像的后序遍历:1)后序遍历右子树,2)后序遍历左子树,3)访问根节点;
如果两个迭代器在每次遍历时取出的节点的值都相同,那么这棵树就是对称的。
后序遍历的解题思路与图解请见:LeetCode题解-145-Binary Tree Postorder Traversal
代码
public class Solution101_DFS_iterator {
public boolean isSymmetric(TreeNode root) {
TreeNode leftIterator = root, rightIterator = root;
TreeNode leftLastVisit = null, rightLastVisit = null;
Deque<TreeNode> leftStack = new LinkedList<TreeNode>(), rightStack = new LinkedList<TreeNode>();
int leftDepth= 0, rightDepth = 0;
if (leftIterator != null)
leftStack.push(leftIterator);
if (rightIterator != null)
rightStack.push(rightIterator);
while (!leftStack.isEmpty() && !rightStack.isEmpty()){
while (leftStack.peek() != null){
TreeNode currentNode = leftStack.peek();
leftStack.push(currentNode.left);
leftDepth++;
}
leftStack.pop();
while (rightStack.peek() != null){
TreeNode currentNode = rightStack.peek();
rightStack.push(currentNode.right);
rightDepth++;
}
rightStack.pop();
if (!leftStack.isEmpty()){
TreeNode leftStackCurrentNode = leftStack.peek();
if (leftStackCurrentNode.right == null || leftStackCurrentNode.right == leftLastVisit){
leftLastVisit = leftStack.pop();
leftStack.push(null);
leftDepth--;
}
else{
leftStack.push(leftStackCurrentNode.right);
}
}
if (!rightStack.isEmpty()){
TreeNode rightStackCurrentNode = rightStack.peek();
if (rightStackCurrentNode.left == null || rightStackCurrentNode.left == rightLastVisit){
rightLastVisit = rightStack.pop();
rightStack.push(null);
rightDepth--;
}
else{
rightStack.push(rightStackCurrentNode.left);
}
}
if (leftDepth != rightDepth)
return false;
if (leftLastVisit == null && rightLastVisit == null)
continue;
else if (leftLastVisit == null && rightLastVisit != null)
return false;
else if (leftLastVisit != null && rightLastVisit == null)
return false;
else if (leftLastVisit.val != rightLastVisit.val)
return false;
}
return true;
}
}