题目:
题解一:
- 先将二叉树填充为满二叉树
- 层次遍历二叉树每一层
- 如果是一个对称二叉树,层次遍历列表也必然对称
public boolean isSymmetric(TreeNode root) {
List<Integer> list = new ArrayList<>();
// 树深度
int treeDepth = getTreeDepth(root);
// 填充树节点
fillTree(root, treeDepth, 1);
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.add(root);
}
// 层次遍历,比较每一层节点是否对称
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
list.add(node.val);
}
// 判断当前层节点是否对称
for (int i = 0, j = list.size() - 1;i <= j;i++, j--) {
if (!list.get(i).equals(list.get(j))) {
return false;
}
}
// 如果当前层都是对称的,继续比较下一层,移除当前层已比较的节点
list.clear();
}
return true;
}
/**
* 将一个二叉树填充为满二叉树
*
* @param root 根节点
* @param treeDepth 树深度
* @param currentDepth 当前深度
*/
private void fillTree(TreeNode root, int treeDepth, int currentDepth) {
if (root == null) {
return;
}
// 已经到达最大,停止填充节点
if (treeDepth == currentDepth) {
return;
}
if (root.left == null) {
// 填充节点,这里填充的节点设置一个默认值
root.left = new TreeNode(-100000);
}
if (root.right == null) {
// 填充节点,这里填充的节点设置一个默认值
root.right = new TreeNode(-100000);
}
fillTree(root.left, treeDepth, currentDepth+1);
fillTree(root.right, treeDepth, currentDepth+1);
}
/**
* 获取树的最大深度
*
* @param root 根节点
* @return 树的深度
*/
int getTreeDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(getTreeDepth(root.left) + 1, getTreeDepth(root.right) + 1);
}
时间复杂度:O(n)
题解二:
从定义出发,对称条件如下:
- 根节点为空,结果对称
- 根节点不为空,左右子树对称,结果对称
左右子树对称判断条件:
- 左子树的左树 == 右子树的右树
- 左子树的右树 == 右子树的左树
public boolean isSymmetric(TreeNode root) {
// 空树算对称
if (root == null) {
return true;
}
// 比较左右两树是否对称
return compare(root.left, root.right);
}
/**
* 比较两棵树是否对称
*
* @param left 左树
* @param right 右树
* @return true:相等,false:不相等
*/
private boolean compare(TreeNode left, TreeNode right) {
if (left == null && right == null) {
return true;
}
if (left != null && right != null) {
// 节点值不相等,证明不对称
if (left.val != right.val) {
return false;
}
// 比较下一层
// 左.左 == 右.右
// 左.右 == 右.左
return compare(left.left, right.right) && compare(left.right, right.left);
}
return false;
}
时间复杂度:O(n)