-
Difficulty: Easy
-
Related Topics: Tree, Depth-first Search, Breadth-first Search
Description
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
给一棵二叉树,判断它是否是自身的镜像(也就是关于 root
轴对称)
For example, this binary tree [1, 2, 2, 3, 4, 4, 3]
is symmetric:
例如,二叉树 [1, 2, 2, 3, 4, 4, 3]
是对称的:
1
/
2 2
/ /
3 4 4 3
But the following [1, 2, 2, null, 3, null, 3]
is not:
但二叉树 [1, 2, 2, null, 3, null, 3]
不是:
1
/
2 2
3 3
Follow up
Solve it both recursively and iteratively.
以迭代和递归两种方法解决。
Solution
迭代解法:层序遍历
如果一棵二叉树是左右对称的,那么其每一层节点的排布也应该是左右对称的。可以通过层序遍历找出每一层的所有节点,再检查这个节点列表是不是对称的。需要注意的是,层序遍历的时候,null
节点也是需要被考虑进去的,这样当树的层级过深时会有 MLE 的风险(特别是层级很深的稀疏树,一层下来大部分节点都是 null
,占据无意义的空间。实际上我第一次提交就爆了内存)。问题出在层序遍历时往下扩张的过程,如果一个节点本身为 null
,那就没有必要继续往下扩展了,这样可以节约大量内存,代码如下:
/**
* Example:
* var ti = TreeNode(5)
* var v = ti.`val`
* Definition for a binary tree node.
* class TreeNode(var `val`: Int) {
* var left: TreeNode? = null
* var right: TreeNode? = null
* }
*/
import java.util.*
class Solution {
fun isSymmetric(root: TreeNode?): Boolean {
if (root == null) {
return true
}
val queue: Queue<TreeNode?> = LinkedList()
queue.offer(root)
while (queue.isNotEmpty()) {
val size = queue.size
val values = arrayListOf<Int?>()
for (i in 1..size) {
val node = queue.poll()
values.add(node?.`val`)
// 只对非 null 的节点进行扩展
node?.let {
queue.offer(it.left)
queue.offer(it.right)
}
}
if (values.all { it == null }) {
break
}
if (!values.isSymmetric()) {
return false
}
}
return true
}
private fun List<Int?>.isSymmetric(): Boolean {
if (this.size < 2) {
return true
}
var left = 0
var right = this.lastIndex
while (left < right) {
if (this[left] != this[right]) {
return false
}
left++
right--
}
return true
}
}
递归解法(来自 discussion):
判断一个树是否镜像,则需要判断其左右子树是否能够通过翻转变化相等。这样就有和比较两棵树是否相等类似了,只不过递归调用的过程中,我们判断的是 left.right
和 right.left
以及 left.left
和 right.right
这两组是否相等,代码如下:
/**
* Example:
* var ti = TreeNode(5)
* var v = ti.`val`
* Definition for a binary tree node.
* class TreeNode(var `val`: Int) {
* var left: TreeNode? = null
* var right: TreeNode? = null
* }
*/
class Solution {
fun isSymmetric(root: TreeNode?): Boolean {
return root == null || isSymmetric(root.left, root.right)
}
private fun isSymmetric(left: TreeNode?, right: TreeNode?): Boolean {
if (left == null || right == null) {
return left == right
}
if (left.`val` != right.`val`) {
return false
}
return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left)
}
}