题目
检查一个二叉树是否轴对称
思路分析
根据题干可以看出,既然要依次判断“轴”两边的结点是否对称相等,就要对二叉树进行遍历。但是由于是需要二叉树轴对称,所以不能用传统的遍历方法,需要加以变通。
由上图可看出,除了1、2层的节点可以之间进行比较外,第三层开始就需要开始变通了。
在比较完第二层节点后,可知 A 与 A’ 对称相等。下一步需要比较的是;
- A 的左孩子与 A’ 的右孩子
- A 的右孩子与 A’ 的左孩子
从这里就可以发现其遍历规律了,代码实现将分为递归与非递归的方式遍历。
基本遍历的实现细节可以看这里:【数据结构】二叉树的前、中、后序、深度、广度遍历(图、文、代码)
代码实现
非递归实现:
/**
* 对称二叉树
* @param root
* @return
*/
public boolean isSymmetric(TreeNode root) {
if(root == null || (root.left == null && root.right == null)) return true;
//初始化广度遍历所需要的队列
Queue<TreeNode> treeQueue = new LinkedList<>();
treeQueue.offer(root.left); //将根节点的左右孩子入队
treeQueue.offer(root.right);
while (!treeQueue.isEmpty()){
//获得队头的两个元素
TreeNode left = treeQueue.poll(); //表示对称轴左边
TreeNode right = treeQueue.poll(); //表示对称轴右边
//如果两棵树的当前结点都为空,继续循环
if (left == null && right == null) continue;
//如果其中一个节点为空或者两个节点不相等 返回false
if (left == null || right == null || left.val != right.val) return false;
//进行入队操作 注意顺序
//左子树的左孩子和右子树的右孩子
treeQueue.offer(left.left);
treeQueue.offer(right.right);
//左子树的右孩子和右子树的左孩子
treeQueue.offer(left.right);
treeQueue.offer(right.left);
}
return true;
}
递归实现:
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return dfs(root.left,root.right);
}
boolean dfs(TreeNode rootLeft, TreeNode rootRight){
//如果两棵树的当前结点都为空,继续循环
if(rootLeft == null && rootRight == null) return true;
//如果其中一个节点为空或者两个节点不相等 返回false
if(rootLeft == null || rootRight == null || rootLeft.val != rootRight.val) {
return false;
}
//左子树的左孩子和右子树的右孩子、左子树的右孩子和右子树的左孩子分别递归
return dfs(rootLeft.left,rootRight.right)&&dfs(rootLeft.right,rootRight.left);
}
总结
遍历的特殊形式,思维需要从传统遍历的方法进行发散,但是换汤不换药