文章目录


前言

哈喽,我是长路,目前刚刚大三,方向是后端也偶尔捣鼓下前端,现在的主语言是Java。之前一大段时间都是在学习web开发的一些技术,就很久没有进行类似于数据结构、算法之类的学习与刷题,打算这段时间拾起来好好学一学、搞一搞。

这段时间也是机缘巧合看到草帽路飞的博客,加了自学群,正巧看到博主组织在群里组织了leetcode刷题打卡活动,我也就参与进来,为期一个月,打算坚持每天都花一些时间做一些题目,并通过博客的方式来进行记录。

 




题目

题目来源leetcode

leetcode地址:​​101. 对称二叉树​​,难度:简单。

题目描述(摘自leetcode):

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1
/ \
2 2
/ \ / \
3 4 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
1
/ \
2 2
\ \
3 3

进阶:
你可以运用递归和迭代两种方法解决这个问题吗?




题解

NO1:递归法

思路:使用递归来进行不断左右节点的比对,这里的左右节点指的是对应的左右外侧或内侧节点。递归方法中包含两个参数,一个是左节点,另一个是右节点。

这里引用一下教程图:​​代码随想录​​,下面每一层我都使用了对应不同的颜色来进行配对比较,同样每次的递归方法也是如此进行比较的。

leetcode【二叉树—简单】 101.对称二叉树_职场和发展

代码

public boolean isSymmetric(TreeNode root) {
return compareLeftAndRight(root.left,root.right);
}

public boolean compareLeftAndRight(TreeNode left,TreeNode right){
//出口
//不对称情况:①某个节点为null,另一个节点不为null。②左右节点值不相等。
if(left == null && right != null){
return false;
}else if(left != null && right == null){
return false;
}else if(left == null && right == null ){ //对于两个null直接返回true。这里防止下面执行出现空指针
return true;
}else if(left.val != right.val){
return false;
}

//若是left与right的值相同,那么进行下面左右子节点的比较
return compareLeftAndRight(left.left,right.right) && compareLeftAndRight(left.right,right.left);
}

leetcode【二叉树—简单】 101.对称二叉树_算法_02

该题的递归中,若是出现不对称的情况时,其他情况会依旧执行下去,将所有的节点进行比对,这样的话就会造成没有必要的比较,我们这里来进行调整,通过一个属性flag来进行标识是否结束:

private boolean flag = true;

public boolean isSymmetric(TreeNode root) {
compareLeftAndRight(root.left,root.right);
return flag;
}

public void compareLeftAndRight(TreeNode left,TreeNode right){
if(!flag){
return;
}
//出口
//不对称情况:①某个节点为null,另一个节点不为null。②左右节点值不相等。
if(left == null && right != null){
flag = false;
return;
}else if(left != null && right == null){
flag = false;
return;
}else if(left == null && right == null ){
return;
}else if(left.val != right.val){
flag = false;
return;
}

//若是left与right的值相同,那么进行下面左右子节点的比较
compareLeftAndRight(left.left,right.right);
if(!flag){
return;
}
compareLeftAndRight(left.right,right.left);
}

这样的话可以避免当出现不对称情况时,其他无意义的比较了以及额外的递归方法!

leetcode【二叉树—简单】 101.对称二叉树_算法_03




NO2:迭代法(队列)

思路:其实与递归的思路大致相同,同样也是比较的左右节点(同外侧或内侧),只不过这里会使用队列来进行临时存储要比对的两个左右节点,每次出队同时出队两个,入队时要入4个(每个节点都有左右孩子)。

代码

//迭代法:使用队列
public boolean isSymmetric(TreeNode root) {
Deque<TreeNode> queue = new LinkedList<>();
if(root == null){
return true;
}
queue.offer(root.left);
queue.offer(root.right);
while(!queue.isEmpty()){
//每次出队2个元素
TreeNode nodeLeft = queue.poll();
TreeNode nodeRight = queue.poll();
if(nodeLeft == null && nodeRight != null){
return false;
}else if(nodeLeft != null && nodeRight == null){
return false;
}else if(nodeLeft == null && nodeRight == null){
continue;
}else if(nodeLeft.val != nodeRight.val){
return false;
}

//依次入队
queue.offer(nodeLeft.left);
queue.offer(nodeRight.right);
queue.offer(nodeLeft.right);
queue.offer(nodeRight.left);
}
return true;
}

leetcode【二叉树—简单】 101.对称二叉树_递归_04

上面的是先入队,之后来进行统一判断的,后来我又写了一个在入队时进行判断的,写完后想了想实际上效果也不大,因为最多仅仅只是提前来对两对节点进行判断而已,这里的话就贴一下:

//迭代法:使用队列
public boolean isSymmetric(TreeNode root) {
Deque<TreeNode> queue = new LinkedList<>();
if(root == null || isNull(root.left,root.right)){
return true;
}
if(!addQueue(root.left,root.right,queue)){
return false;
}

while(!queue.isEmpty()){
//每次出队2个元素
TreeNode nodeLeft = queue.poll();
TreeNode nodeRight = queue.poll();

if(!isNull(nodeLeft.left,nodeRight.right)){
if(!addQueue(nodeLeft.left,nodeRight.right,queue)){
return false;
}
}
if(!isNull(nodeLeft.right,nodeRight.left)){
if(!addQueue(nodeLeft.right,nodeRight.left,queue)){
return false;
}
}

}
return true;
}

public boolean addQueue(TreeNode node1,TreeNode node2,Deque queue){
if(isSymmetry(node1,node2)){
queue.offer(node1);
queue.offer(node2);
return true;
}else{
return false;
}
}

public boolean isNull(TreeNode leftNode,TreeNode rightNode){
return leftNode == null && rightNode == null;
}

/**
* 判断是否对称
* @param left
* @param right
* @return true表示允许将两个节点入队,false则表示不对称
*/
public boolean isSymmetry(TreeNode left,TreeNode right){
if(left == null && right != null){
return false;
}else if(left != null && right == null) {
return false;
}else if(left.val == right.val){
return true;
}
// }else if(left == null && right == null){ //该判断要进行抽离
// return true;
// }
return false;
}

leetcode【二叉树—简单】 101.对称二叉树_二叉树_05




参考文章

[1]. ​​leetcode题解​

[2]. ​​ 代码随想录—101. 对称二叉树​