• 剑指 Offer 28. 对称的二叉树


    思路

    一开始想用左根右遍历的序列和右根左遍历的序列进行比较,如果相等则镜像对称。后来发现这种方式不对,比如样例[1, 2, 2, null, 2]就不是镜像对称的,但这种方法会返回true。

    方法一:递归

     1 /**
     2  * Definition for a binary tree node.
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     bool isSymmetric(TreeNode* root) {
    13         if(root == NULL)    
    14             return true;
    15         return check(root->left, root->right);
    16     }
    17 
    18     bool check(TreeNode* L, TreeNode* R) {
    19         if(L == NULL && R == NULL)
    20             return true;
    21         
    22         if(L != NULL && R != NULL && L->val == R->val)
    23             return check(L->left, R->right) && check(L->right, R->left); 
    24         
    25         return false;
    26     }
    27     
    28 };

    复杂度分析:

    时间复杂度 O(N) : 其中 N 为二叉树的节点数量,每次执行 check() 可以判断一对节点是否对称,因此最多调用 N/2 次 check() 方法。
    空间复杂度 O(N) : 最差情况下,二叉树退化为链表,系统使用 O(N)大小的栈空间。

    方法二:非递归(迭代)

    方法一中我们用递归的方法实现了对称性的判断,那么如何用迭代的方法实现呢?

    首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。

    初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。

    当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

     1 /**
     2  * Definition for a binary tree node.
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     bool isSymmetric(TreeNode* root) {
    13         if(root == NULL)
    14             return true;
    15         return check(root->left, root->right);
    16     }
    17 
    18     bool check(TreeNode *u, TreeNode *v) {
    19         queue <TreeNode*> q;
    20         q.push(u); q.push(v);
    21         while (!q.empty()) {
    22             u = q.front(); q.pop();
    23             v = q.front(); q.pop();
    24             if (!u && !v) continue;
    25             if ((!u || !v) || (u->val != v->val)) return false;
    26 
    27             q.push(u->left); 
    28             q.push(v->right);
    29 
    30             q.push(u->right); 
    31             q.push(v->left);
    32         }
    33         return true;
    34     }
    35 };

    复杂度分析:

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

    参考

    力扣官方题解-对称二叉树

    面试题28. 对称的二叉树(递归,清晰图解)

  • 相关阅读:
    T-SQL over()函数在单个表中的聚合
    jQuery EasyUI DataGrid API 中文文档
    ASP.Net UpdatePanel控件(转)
    java多线程系类:基础篇:03Thread中的start()和run()的区别
    java多线程系类:基础篇:02常用的实现多线程的两种方式
    java多线程系类:基础篇:01基本概念:
    完全二叉树的概念
    007商城项目:商品列表查询-需求分析,以及Spinmvc的访问知识
    006商城项目:该项目的路径访问问题
    githup上传代码
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/13883794.html
Copyright © 2020-2023  润新知