对称二叉树
要求给定一个二叉树的根节点root检查它是否轴对称即左右镜像对称。示例 1输入root [1,2,2,3,4,4,3]树的结构如下Text1 / \ 2 2 / \ / \ 3 4 4 3输出true解释左右两边完全镜像对称外侧都是 3内侧都是 4。示例 2输入root [1,2,2,null,3,null,3]树的结构如下Text1 / \ 2 2 \ \ 3 3输出false解释虽然节点值相同但结构不对称右边缺失了左孩子左边缺失了左孩子方向一致而不是镜像。思路判断一棵树是否对称不能只看一个节点的左右两个孩子是否相等而是要看这棵树的左子树和右子树是不是相互“镜像”的。既然要比较两棵子树我们就需要一个辅助函数同时接收两个节点左边的节点和右边的节点往下进行对比。 两棵子树相互镜像必须满足以下条件按顺序判断两个节点都是空null说明到底了它们对称。一个为空另一个不为空结构不一样肯定不对称。两个都不为空但里面的值不一样不对称。如果值一样就继续往下对比核心左子树的左孩子必须跟右子树的右孩子对比这叫比较外侧。左子树的右孩子必须跟右子树的左孩子对比这叫比较内侧。 只有当外侧和内侧都镜像对称时这两部分才算完全对称。题解Java// 二叉树节点的标准定义classTreeNode{intval;TreeNodeleft;TreeNoderight;TreeNode(intx){valx;}}publicclassSymmetricTree{publicstaticvoidmain(String[]args){// 测试示例1构造对称二叉树 [1,2,2,3,4,4,3]TreeNoderoot1newTreeNode(1);root1.leftnewTreeNode(2);root1.rightnewTreeNode(2);root1.left.leftnewTreeNode(3);root1.left.rightnewTreeNode(4);root1.right.leftnewTreeNode(4);root1.right.rightnewTreeNode(3);booleanresult1isSymmetric(root1);System.out.println(示例1结果: result1);// 预期输出: true// 测试示例2构造不对称二叉树 [1,2,2,null,3,null,3]TreeNoderoot2newTreeNode(1);root2.leftnewTreeNode(2);root2.rightnewTreeNode(2);root2.left.rightnewTreeNode(3);root2.right.rightnewTreeNode(3);booleanresult2isSymmetric(root2);System.out.println(示例2结果: result2);// 预期输出: false// 边界测试空树booleanresult3isSymmetric(null);System.out.println(空树测试: result3);// 预期输出: true}// 主函数publicstaticbooleanisSymmetric(TreeNoderoot){// 如果树是空的本身就是对称的if(rootnull){returntrue;}// 把根节点的左孩子和右孩子传给辅助函数进行镜像比对returncheckMirror(root.left,root.right);}// 辅助函数判断 leftNode 和 rightNode 是否镜像对称publicstaticbooleancheckMirror(TreeNodeleftNode,TreeNoderightNode){// 1. 如果两个都为空说明对比到了叶子节点的下面是对称的if(leftNodenullrightNodenull){returntrue;}// 2. 如果其中一个为空另一个不为空说明结构不对称if(leftNodenull||rightNodenull){returnfalse;}// 3. 两个都不为空但值不一样也不对称if(leftNode.val!rightNode.val){returnfalse;}// 4. 当前节点的值一样继续往下递归比较// 比较外侧左边的左孩子 vs 右边的右孩子booleanoutsidecheckMirror(leftNode.left,rightNode.right);// 比较内侧左边的右孩子 vs 右边的左孩子booleaninsidecheckMirror(leftNode.right,rightNode.left);// 只有外侧和内侧同时对称这两棵子树才算真正的镜像对称if(outsidetrueinsidetrue){returntrue;}else{returnfalse;}}}注意判断顺序非常重要在辅助函数checkMirror中必须先判断节点是否为null再判断节点的值leftNode.val ! rightNode.val。如果顺序反了当节点是null时去调用.val会触发NullPointerException空指针异常。递归的核心思维初学者容易在一个函数里去死磕root.left.val root.right.val然后不知道下一层怎么写。遇到比较“左右两侧”的树形问题一定要想到剥离出一个带有两个参数的辅助函数让这两个节点自己去一层层往下对比。外侧与内侧的对应关系千万不要写成checkMirror(leftNode.left, rightNode.left)既然是镜像照镜子左边的左边对应的必然是右边的右边最外围。左边的右边对应的是右边的左边靠里面的位置。