vlambda博客
学习文章列表

每日算法——对称二叉树

大家好,我是宇哥

前言

最近一直在更新关于树的相关知识,然后就去leetcode上整个算法玩玩,万万没想到,还差大远。以后坚持每日一道算法题。第二天


题目:

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

https://leetcode-cn.com/problems/symmetric-tree/


例如,二叉树 [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


进阶:

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



解题思路

  1. 递归思想,

  2. 判断父节点为null 结束返回true

  3. 判断父节点的子,左节点和右节点为为null 并且相等返回true,否则 返回false

  4. 左节点的值和右节点的值不相等返回false,否则 继续递归左节点和右节点


终解AC代码:自己经过不懈尝试最终成功了,好的开始

/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */class Solution { public boolean isSymmetric(TreeNode root) {        // 空节点直接返回        if (root == null) return true; return leftRight(root.left,root.right); }    /**    * 递归调用     * left 左节点    * right 右节点    **/ private boolean leftRight(TreeNode left, TreeNode right) {        // 节点判null if (left == null || right == null) return left == right;        // 对称节点值判断  if (left.val != right.val) return false; //左节点的 左,右节点的 右 | 左节点的 右,右节点的 左 return leftRight(left.left,right.right) && leftRight(left.right,right.left); }}

复杂度分析


假设树上一共 n 个节点。

时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)。

空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。


大佬们的解法和思路:

首先我们引入一个栈/队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

代码如下:

class Solution { public boolean isSymmetric(TreeNode root) { if (root == null) return true; //构建一个栈 Stack<TreeNode> stack = new Stack<>(); //向里添加树左右节点 stack.push(root.left); stack.push(root.right); //栈不空就循环 while(!stack.empty()) { //弹出栈里元素 TreeNode n1 = stack.pop();  TreeNode n2 = stack.pop(); //进行非空判断 if (n1 == null && n2 == null) continue; //进行对称判断 if (n1 == null || n2 == null || n1.val != n2.val ) return false; //向栈里添加子树叉,然后继续循环 n1(左)n2(右) //顺序 左节点的 左,右节点的 右  stack.push(n1.left); stack.push(n2.right); //顺序 左节点的 右,右节点的 左 stack.push(n1.right); stack.push(n2.left); //添加元素之后就可以继续循环了  } return true; }

复杂度分析

时间复杂度:O(n)

空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。


小结:

day2独立写出第一个算法题,虽然是简单题,但也很 nice。一步步来。

与你同在架构之路
一个专注于java软件架构师成长专栏
28篇原创内容
Official Account

喜欢的【转发一波】【点点在看】【点赞一下】