【代码随想录训练营第42期 Day14打卡 二叉树Part2-LeetCode 226.翻转二叉树 101. 对称二叉树 104.二叉树的最大深度 111.二叉树的最小深度

目录

一、做题心得

二、题目与题解

题目一:226.翻转二叉树 

题目链接

题解:1:BFS

题解2:递归

题目二:101. 对称二叉树

题目链接

题解1:BFS

 题解2:递归

题目三:104.二叉树的最大深度

题目链接

题解:递归

题目四:111.二叉树的最小深度

题目链接

题解一:BFS

题解二:递归

三、小结


一、做题心得

今天是代码随想录打卡的第14天,学习的是二叉树部分的part2。今天的题目运用到了不少昨天的知识,包括递归的思想,层序遍历的实现(昨天打卡有个模板),栈与队列的应用等等。整体而言,迭代的难度都不算大,但是递归思路可能不太容易理解,等会会对此进行一下分析。

话不多说,直接步入正题。

二、题目与题解

题目一:226.翻转二叉树 

题目链接

226. 翻转二叉树 - 力扣(LeetCode)

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

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

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目范围在 [0, 100] 内
  • -100 <= Node.val <= 100
题解:1:BFS

这个题的要求就是从右往左的层序遍历,这就与昨天层序遍历(模板题)的思路一样,只不过先进的左节点得后出,只需要将存储树的节点queue改成stack既可,就能实现先进后出,进而实现从右往左的层序遍历。当然,这道题也可以直接用queue,只需要改成右节点先进队列既可,这样就是经典的BFS解法,大家可以去尝试一下。

不会层序遍历BFS的可以看看昨天打卡整理的模板题:【代码随想录训练营第42期 Day13打卡 二叉树的遍历-- LeetCode 144. 二叉树的前序遍历 94. 二叉树的中序遍历 145. 二叉树的后序遍历 102. 二叉树的层序遍历-CSDN博客

这里给出BFS思路(其实用queue来实现更纯粹,这里只是提供一下这个思路)的代码:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {            
        stack<TreeNode*> st;
        if (root == nullptr)    return root;
        if (root != nullptr)    st.push(root);
        while (!st.empty()) {
            int size = st.size();           //标记当前层的大小(节点数)
            for(int i = 0; i < size; i++) {
                TreeNode* node = st.top();      //当前节点
                st.pop();
                TreeNode* temp = node->left;      //临时节点,用于交换当前节点node的左右孩子
                node->left = node->right;
                node->right = temp;
                if(node->left)     st.push(node->left);     //进栈:先左后右。出栈相反
                if(node->right)    st.push(node->right); 
            }
        }
        return root;         
    }
};

注意与昨天层序遍历不同的地方:这里返回值类型为TreeNode* ,不是单独开个数组存储。

题解2:递归

递归的思路其实也简单,就是先对与根节点而言,交换左右孩子的位置,然后分别对左右孩子进行同样的操作,一直往后遍历交换左右孩子直到终止。

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr)    return root;        //终止条件
        TreeNode* temp = root->left;        //交换根的左右孩子
        root->left = root->right;
        root->right = temp;
        root->left = invertTree(root->left);        //递归;对根的左右孩子进行相同操作
        root->right = invertTree(root->right);
        return root;
    }
};

题目二:101. 对称二叉树

题目链接

101. 对称二叉树 - 力扣(LeetCode)

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

示例 1:

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

示例 2:

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

提示:

  • 树中节点数目在范围 [1, 1000] 内
  • -100 <= Node.val <= 100
题解1:BFS

这个题也是用到的BFS的思想。从队列中取出两个节点(leftnode和 rightnode),这两个节点是当前待检查的一对对称节点。(外层两对称以及内层两对称都能表示)

由于昨天对于层序遍历的思想有了具体描述,这里直接上代码:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> q;
        q.push(root->left);
        q.push(root->right);
        while(!q.empty()){
            TreeNode* leftnode=q.front();
            q.pop();
            TreeNode* rightnode=q.front();
            q.pop();
            if(leftnode == nullptr && rightnode == nullptr)  continue;
            if((leftnode == nullptr && rightnode != nullptr) || (leftnode != nullptr && rightnode == nullptr) || leftnode->val != rightnode->val)  return false;
            q.push(leftnode->left);         //外层
            q.push(rightnode->right);
            q.push(leftnode->right);        //内层
            q.push(rightnode->left);
        }

        return true;
    }
};
 题解2:递归

我们要自己定义一个函数,来比较左右子树是否对称。使用递归,首先要确定终止条件,表示各种可直接得到结果的特殊情况,再对于一般情况进行递归。

代码及详细思路如下:

class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right) {     //比较左右子树left,right
        //终止条件(特殊情况)
        if (left == nullptr && right != nullptr)    return false;           
        else if (left != nullptr && right == nullptr)   return false;
        else if (left == nullptr && right == nullptr)   return true;
        else if (left->val != right->val)   return false;
        //递归
        else {          
        bool outside = compare(left->left, right->right);   //比较外层即左子树的左部分 与 右子树的右部分
        bool inside = compare(left->right, right->left);    //比较内层即左子树的右部分 与 右子树的左部分
        return outside && inside;  
        }

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

题目三:104.二叉树的最大深度

题目链接

104. 二叉树的最大深度 - 力扣(LeetCode)

给定一个二叉树 root ,返回其最大深度。

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

示例 1:

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

示例 2:

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

提示:

  • 树中节点的数量在 [0, 104] 区间内。
  • -100 <= Node.val <= 100
题解:递归

没什么好说的,直接一个简单的递归。

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == 0)     return 0;     //根节点为空时,同时也是作为递归的终止条件
        return max(maxDepth(root->left),maxDepth(root->right))+1;   //使用递归:二叉树的最大深度为根节点的左右子树深度的较大者+1
    }
};

题目四:111.二叉树的最小深度

题目链接

111. 二叉树的最小深度 - 力扣(LeetCode)

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

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

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

示例 1:

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

示例 2:

输入:root = [2,null,3,null,4,null,5,null,6]
输出:5

提示:

  • 树中节点数的范围在 [0, 105] 内
  • -1000 <= Node.val <= 1000
题解一:BFS

再次套用BFS二叉树层序遍历模板。这个题需要注意的就是depth的使用(用来记录深度),以及遍历终止的条件--遍历的某个节点左子树和右子树都为空。

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> q;     //使用队列进行BFS,从而实现层序遍历
        q.push(root);
        while(!q.empty()) {
            int size = q.size();       //size记录每层节点个数
            depth++;        //记录最小深度,从根节点记作depth=1
            for (int i = 0; i < size; i++) {
                TreeNode* node = q.front();
                q.pop();
                if (node->left)     q.push(node->left);     //先进先出
                if (node->right)    q.push(node->right);
                if (!node->left && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出
                    return depth;
                }
            }
        }
        return depth;
    }
};
题解二:递归

注意这个题和上一道很相似,但不能直接套用。因为只有左子树或者右子树的话,最小值就恒定为0,也就是说不能直接一步到位,我们必须得考虑左子树或者右子树为空的情况。

代码如下:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == nullptr)    return 0;       //递归终止条件(root为空的特殊情况)
        //递归(3种情况)
        if (root->left == nullptr && root->right != nullptr) {      //左子树为空,最小深度就是右子树的最小深度+1
            return minDepth(root->right) + 1;
        }
        if (root->left != nullptr && root->right == nullptr) {     //右子树为空,最小深度就是左子树的最小深度+1
            return  minDepth(root->left) + 1;
        }
        //如果当前节点的左右子树都不为空,则取左右子树最小深度的较小值+1
        return min(minDepth(root->left), minDepth(root->right)) + 1;
    }
};

三、小结

今天的打卡到此也就结束了,明天继续加油。最后,我是算法小白,但也希望终有所获。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值