题目描述:
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
限制:
0 <= 节点个数 <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
首先来看看《剑指offer》上的思路:
在用前序遍历法遍历二叉树的时候,是先访问根节点,再访问左子节点,再访问右子节点,按照这个顺序访问二叉树的全部节点。但是,如果二叉树是对称的时候,改变一下遍历的顺序:先访问根节点,再访问右子节点,再访问左子节点。按照这样的顺序得到的节点的值应该是和前序遍历得到的节点顺序是一样的。但是要注意的是,为了预防上面的第二种情况,顺序都是一样的,但是结构不一样,把空值的节点也记录进去就能解决。
(这个思路很好理解,但是在LeetCode的系统上好像出了点问题,测试用例里面都能返回正确的结果,但是提交就是显示错误)
此外,还在系统上看到了牛人的思路:
分两条路走,一条往左,一条往右,每走一步比较当前的节点是不是一样的,一样的再开启下一步:在第一层递归的时候,就是根节点的左子节点和右子节点的比较,完了比较没有返回false,就开启根节点的左子节点的左子节点和根节点的右子节点的右子节点的比较,完了还没返回false,再开启根节点的左子节点的右子节点和根节点的右子节点的左子节点的比较(非常拗口),如果都没有返回false,就返回true。
代码(Java):
//LeetCode思路
public class Solution {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(2);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(4);
root.right.left = new TreeNode(4);
root.right.right = new TreeNode(3);
System.out.println(isSymmetric(root));
}
public static boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return dfs(root.left,root.right); //从根节点的左右节点先比较
}
public static boolean dfs(TreeNode left,TreeNode right) {
if(left == null && right == null) { //一路往下,直到两边都没有节点了,返回true
return true;
}
if(left == null || right == null) { //不是两边都为空,只有一边为空,肯定不是对称的
return false;
}
//比较完当前节点之后,开启下一层递归,比较输入左节点的左子节点和输入右节点的右子节点,然后再开启比较输入左节点的右子节点和输入右节点的左子节点
return left.val==right.val && dfs(left.left,right.right) && dfs(left.right,right.left);
}
}
```java
//剑指offer上的思路
public class doingmyself {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(2);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(4);
root.right.left = new TreeNode(4);
root.right.right = new TreeNode(3);
System.out.println(isSymmetric(root));
}
//初始化两个list,用来存放不同的遍历顺序得到的节点的值
static List<Integer> list1 = new ArrayList<Integer>();
static List<Integer> list2 = new ArrayList<Integer>();
public static boolean isSymmetric(TreeNode root) {
if(root == null) return true;
getNodefromleft(root);
getNodefromright(root);
//这个list的内容是 根节点到左子节点到右子节点的顺序得到的
for(int i = 0;i<list1.size();i++) {
System.out.print(list1.get(i)+"\t");
}
System.out.println();
//这个list的内容是 根节点到右子节点到左子节点的顺序得到的
for(int i = 0;i<list2.size();i++) {
System.out.print(list2.get(i)+"\t");
}
for(int i = 0;i<list1.size();i++) {
if(list1.get(i) != list2.get(i)) {
return false;
}
}
return true;
}
//根据 根节点到左子节点到右子节点的顺序 把二叉树节点的值放进list里面
public static void getNodefromleft(TreeNode root) {
if(root == null) { //空的值也要放进list,预防二叉树全部值都一样,但是结构不对称的情况
list1.add(null);
return;
}
list1.add(root.val); //拿根节点的
getNodefromleft(root.left); //先拿左边的
getNodefromleft(root.right);//再拿右边的
return;
}
public static void getNodefromright(TreeNode root) {
if(root == null) {
list2.add(null);
return;
}
list2.add(root.val);
getNodefromright(root.right);
getNodefromright(root.left);
return;
}
}
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x){
val = x;
}
}