二叉树相关(二):对称二叉树+二叉树的最大深度+二叉树的层序遍历+二叉树的锯齿形遍历+二叉树的层平均值

1.对称二叉树

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

方法一:递归。

如果一个树的左子树和右子树镜像对称,那么这个树是对称的。

class Solution {
public:
    bool check(TreeNode* p,TreeNode* q){
    if(p==NULL&&q==NULL) return true;
    if(p==NULL||q==NULL) return false;//p,q中有一个是空指针,一个不是,则返回false
    return (p->val==q->val)&&check(p->left,q->right)&&check(p->right,q->left);
}
    bool isSymmetric(TreeNode* root) {
        return check(root,root);
    }
};

方法二:迭代。

首先引入队列,这是把递归程序改写为迭代程序的常用方法。参考官方题解:

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

class Solution {
public:
    bool check(TreeNode *u, TreeNode *v) {
        queue <TreeNode*> q;
        q.push(u); q.push(v);
        while (!q.empty()) {
            u = q.front(); q.pop();
            v = q.front(); q.pop();
            if (!u && !v) continue;
            if ((!u || !v) || (u->val != v->val)) return false;

            q.push(u->left); 
            q.push(v->right);

            q.push(u->right); 
            q.push(v->left);
        }
        return true;
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/symmetric-tree/solution/dui-cheng-er-cha-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

层次遍历二叉树。

void LevelTraverse(TreeNode* root){//层次遍历
    if(root==NULL) return;
    TreeNode* temp=nullptr;
    queue <TreeNode*> q;
    q.push(root);
    while(!q.empty()){
        temp=q.front();
        cout<<temp->val<<" "; q.pop();
        if(temp->left!=NULL) q.push(temp->left);
        if(temp->right!=NULL) q.push(temp->right);
    }
    cout<<endl;
}

2.二叉树的最大深度

广度优先搜索的方法。C++的queue类的成员函数有:push()  pop() size() empty() front() back(). 参考官方题解:

我们也可以用「广度优先搜索」的方法来解决这道题目,但我们需要对其进行一些修改,此时我们广度优先搜索的队列里存放的是「当前层的所有节点」。每次拓展下一层的时候,不同于广度优先搜索的每次只从队列里拿出一个节点,我们需要将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展,最后我们用一个变量 ans 来维护拓展的次数,该二叉树的最大深度即为 ans。

class Solution {
public:
    int maxDepth(TreeNode* root) {
       int ans=0;
       if(root==NULL) return 0;
    queue<TreeNode*> q;
    q.push(root);
    while(!q.empty()){
      int sz=q.size();
    while(sz>0){
        TreeNode* node=q.front();q.pop();
        if(node->left) q.push(node->left);
        if(node->right) q.push(node->right);
        sz=sz-1;
    }
    ans=ans+1;
    }
    return ans;
    }
};

3.二叉树的层序遍历

可以借鉴上一道题目的写法,用队列的结构和两层循环。

方法一:BFS

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> array;
    if(root==NULL) return array;
    queue<TreeNode*> q;
    vector<int> d;
    q.push(root);
    while(!q.empty()){
        int sz=q.size();
        while(sz>0){
        TreeNode* node=q.front();q.pop();
        d.push_back(node->val);
        if(node->left) q.push(node->left);
        if(node->right) q.push(node->right);
        sz=sz-1; 
        }
       array.push_back(d);
       d.clear(); 
    }
    return array;
    }
};

方法二:一个最朴素的算法是用(node,level)来表示节点的状态。

4.二叉树的锯齿形遍历

5.二叉树的层平均值

可以使用DFS的递归和非递归的形式;或者BFS。使用递归的DFS执行效率不如BFS。

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root){
        vector<double> res;
        vector<int> count;
        average(root,0,res,count);
        for(int i=0;i<res.size();i++)
            res[i]=res[i]/count[i];
        return res;
}
void average(TreeNode* t,int i,vector<double> &sum,vector<int> &count){//sum和count数组会被修改
    //需要额外记录当前节点所在高度
    if(t==NULL) return;
    if(i<sum.size()){
        sum[i]=sum[i]+t->val;
        count[i]=count[i]+1;
    }
    else{//i=0的话
        sum.push_back(1.0*t->val);
        count.push_back(1);
    }
    average(t->left,i+1,sum,count);
    average(t->right,i+1,sum,count);
} 
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值