Leetcode数据结构入门第十一天(树的应用(1))

之前的文章:树的前序,中序,后序遍历

102. 二叉树的层序遍历

题目描述

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

样例

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

思路

树的层序遍历就是一层一层从左往右访问每个节点,因为队列是FIFO先进先出原则,所以可以用来存储每一层节点,具体实现:因为根节点为第一层,所以先把根节点压入队列,开始遍历,每一层节点数就是队列的长度len,循环len次,每次把队首元素值压入临时一元数组inner中,并出队,再把当前队首元素的左右孩子节点压入队列中(放在后面,不影响该层节点)。循环结束,把当层节点的内层结果压入总结果中,然后继续下一层的循环,直到队列为空,遍历结束。

参考代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        //层序遍历:广度优先搜索
        //遍历结果:逐层表示
        vector<vector<int>> res;
        //如果根节点为空直接返回
        if(root==NULL) return res;

        //用队列存储当前节点的下一层子节点
        queue<TreeNode*> que;
        //初始化:把根节点压入队列
        que.push(root);

        //当队列非空时,将当前队列值存入同一层结果中,并出队,同时让下一层节点入队
        while(!que.empty())
        {
            int len=que.size();//当前队列长度
            //vector<int> inner(len);//内层结果:一开始为空,注意这样新建节点,push_back是在所有节点后新建节点,所以这样会多出几个节点值为0。
            vector<int> inner;
            //i没有实际意义,只是循环len次
            for(int i=0;i<len;i++)
            {
                //获得队头元素,并出队
                TreeNode* node=que.front();
                que.pop();
                //压入队列
                inner.push_back(node->val);
                //当前节点的下层子结点顺便压入队列
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            //循环结束,把当层节点的内层结果压入总结果中
            res.push_back(inner);
        }
        return res;

    }
};

104. 二叉树的最大深度

题目描述

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

样例

输入:[3,9,20,null,null,15,7],
输出:3

思路一

求最大深度,实际上就是判断该树有多少层,所以基本上套用层序遍历(广度优先搜索)的方法即可,因为这里只需要判断层数,所以不需要层序遍历的结果,可以直接化简掉,只需要在每层内层循环后,深度++,最后返回深度即可。

参考代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        //广度优先搜索:即层序遍历
        if(root==NULL) return 0;
        int max=0;
        //队列存储每一层节点值
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty())
        {
            int len=que.size();//表示这一层的节点数
            //遍历len次,把下一层节点从左往右压入队列
            for(int i=0;i<len;i++)
            {
                TreeNode* node=que.front();
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            //每进行一次内层for循环,层数加1
            max++;
        }
        return max;

    }
};

思路二

深度优先搜索(递归法):
如果知道左子树的最大深度和右子树的最大深度,那么最大深度=两者中的最大值+1
不断递归,左子树和右子树的最大深度又可以按照同样方式求出来,而递归终点为根节点为空。

参考代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        //深度优先搜索:递归法
        //递归终点
        if(root==NULL) return 0;
        //递归参数:只需要根节点即可,
        //递归返回值:还是这个最大深度
        return 1+max(maxDepth(root->left),maxDepth(root->right));
        
    }
};

101. 对称二叉树

题目描述

给你一个二叉树的根节点 root , 检查它是否轴对称。

样例一

在这里插入图片描述

输入:root = [1,2,2,3,4,4,3]
输出:true

样例二

在这里插入图片描述

输入:root = [1,2,2,null,3,null,3]
输出:false

参考题解

思路一

递归法:判断二叉树对称,比较的是根节点的左右子树是否相互翻转,实际上就是判断两子树的外侧子节点和内侧子节点是否相等:
(外侧:左子树的左子节点与右子树的右子节点
内侧:左子树的右子节点与右子树的左子节点)
在这里插入图片描述
递归三步走:

  1. 确定递归函数的参数,返回值
    比较的是两个树:左子树,右子树,所以参数为两个树节点,返回值为bool类型
  2. 确定递归终点
    两个树节点数值比较,有三种情况,递归终止:
    (1)左右子树都为空,说明是对称,返回true
    (2)左右子树只有一个为空,不对称,返回false
    (3)左右子树都不为空,但是数值不相等,也是不对称,返回false
  3. 处理单层递归逻辑
    不满足递归终点,说明左右树节点都不为空,且数值相等:可以比较当前左右子树节点的外侧子节点和内侧子节点是否相等,如果左右都对称即返回true,否则为false

参考代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    //递归函数:
    //参数:比较的是两个树:左子树,右子树
    bool compare(TreeNode* left,TreeNode* right)
    {
        //递归终点:
        //左右子树都为空,就是对称的
        if(left==NULL&&right==NULL) return true;
        //有一个为空,一个不为空,不对称
        else if(left==NULL&&right!=NULL||left!=NULL&&right==NULL) return false;
        //左节点的值不等于右节点值,也是不对称
        else if(left->val!=right->val) return false;

        //递归单层逻辑:处理左节点值=右节点值,判断他们子树怎么样
        //外层:左节点的左,右节点的右
        bool out=compare(left->left,right->right);
        //内层:左节点的右,右节点的左
        bool in=compare(left->right,right->left);

        //只有内层和外层都相等才是对称的
        return out&&in;
    }

    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        else return compare(root->left,root->right);

    }
};

思路二

迭代法(不是层序遍历):这里使用队列,其实只是用做一个容器,按照顺序把左右两个子树用于比较的节点存储进去,然后成对取出来比较。
具体实现:首先把root节点的左右子树根节点压入队列,然后开始循环迭代,取出队列中前两个队首元素,即取得当前左右子树的根节点,进行比较,如果有不符合的情况,直接返回,否则继续,判断结束后,分别压入当前左右子树的内侧节点和外侧节点,继续遍历,直到队列为空。

参考代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    //迭代法:队列
    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        queue<TreeNode*> que;
        //初始:先让左右子树的根节点入队
        que.push(root->left);
        que.push(root->right);
        //判断两子树是否对称
        while(!que.empty())
        {
            //取出当前的左右子树根节点,用于比较
            TreeNode* left=que.front();
            que.pop();
            TreeNode* right=que.front();
            que.pop();
            //判断:
            //左右子树都为空
            if(left==NULL&&right==NULL) continue;
            //只有一个为空:不对称,直接返回了
            else if(left==NULL||right==NULL) return false;
            //左右子树节点数值不等
            else if(left->val!=right->val) return false;

            //判断结束后:把当前左右子树的外侧节点和内侧节点压入队列,用于下一层比较
            //外侧节点
            que.push(left->left);
            que.push(right->right);
            //内侧节点
            que.push(left->right);
            que.push(right->left);
        }
        return true;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值