package com.freetymekiyan.algorithms.level.easy;
import com.freetymekiyan.algorithms.utils.Utils.TreeNode;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
* <p>
* For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
* <p>
* | 1
* | / \
* | 2 2
* | / \ / \
* | 3 4 4 3
* But the following [1,2,2,null,3,null,3] is not:
* | 1
* | / \
* | 2 2
* | \ \
* | 3 3
* Note:
* Bonus points if you could solve it both recursively and iteratively.
* <p>
* Company Tags: LinkedIn, Bloomberg, Microsoft
* Tags: Tree, Depth-first Search, Breadth-first Search
*/
public class SymmetricTree {
/**
* Iterative. Stack. DFS.
* Skip root since it's definitely symmetric.
* Push root's children onto a stack if they both exists.
* While stack is not empty:
* | Pop two nodes n1 and n2 from stack to compare.
* | If they are both null, continue.
* | If only one of them is null, or they are not the same value:
* | Not symmetric, return false.
* | Push their children onto stack for the next iteration:
* | In a symmetric way, n1.left and n2.right, then n1.right and n2.left.
*/
private boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
if (root.left == null || root.right == null) {
return root.left == root.right;
}
Deque<TreeNode> s = new ArrayDeque<>();
s.push(root.left);
s.push(root.right);
while (!s.isEmpty()) {
TreeNode n1 = s.pop();
TreeNode n2 = s.pop();
if (n1.val != n2.val) {
return false;
}
if (n1.left != null && n2.right != null) { // Both are not null.
s.push(n1.left);
s.push(n2.right);
} else if (n1.left != null || n2.right != null) { // Only one of them is null.
return false;
}
if (n1.right != null && n2.left != null) {
s.push(n1.right);
s.push(n2.left);
} else if (n1.right != null || n2.left != null) {
return false;
}
}
return true;
}
/**
* Recursive. DFS.
* Depth first search both subtrees, n1 and n2.
* If at least one node is null:
* | Return true if they are both null, otherwise false.
* Then check both current nodes values.
* Check n1.left and n2.right.
* Check n1.right and n2.left.
*/
private boolean isSymmetricRec(TreeNode root) {
if (root == null) {
return true;
}
return dfs(root.left, root.right);
}
private boolean dfs(TreeNode n1, TreeNode n2) {
if (n1 == null || n2 == null) {
return n1 == n2;
}
return n1.val == n2.val && dfs(n1.left, n2.right) && dfs(n1.right, n2.left);
}
}