代码随想录算法训练营day14|226.翻转二叉树、101. 对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度

碎碎念:加油!!!!
参考:代码随想录

226.翻转二叉树

题目链接

226.翻转二叉树

思想

注意本题应该交换指针,而不是数值。本题用前序或者后序最合适。
递归三部曲

  1. 确定递归函数的返回值和参数
  2. 确定终止条件:root == NULL时return root
  3. 处理逻辑:交换root的左孩子和右孩子

**为什么不用中序遍历:**中序的顺序是左中右,先遍历了左子树,回到root后左右子树交换了,那么遍历右子树实际上还是遍历原来的左子树,所以说中序不合适。要写的话也行,就是后面的要改成还处理左子树。

题解

// 前序遍历
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        swap(root->left, root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root == None:
            return root
        root.left, root.right = root.right, root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

反思

写递归的时候要把握住递归的三步。写这道题的时候要清楚自己用的遍历方法,这题写中序遍历的时候有特殊的写法。

101. 对称二叉树

题目链接

101. 对称二叉树

思想

如果左子树和右子树可以相互翻转,就说明这是一个对称二叉树。
看一个树是否为对称二叉树:比较的时候应该比较外侧的节点是否相等,内侧的节点是否相等。
这道题只能使用
后序
,顺序是左右中,因为我们要不断收集左右孩子的信息返回上一个节点,才能知道左右两边比较的结果。
递归三部曲:

  1. 传入的参数:左子树的头结点,右子树的头结点
  2. 终止条件:有以下几种情况

在这里插入图片描述
3. 递归逻辑:值不为空,且相等,则继续向下遍历。判断相等应该看对称的点位,也就是外侧和外侧,内侧和内侧比较。
左节点的左孩子 右节点的右孩子 比较
左节点的右孩子 右节点的左孩子 比较
只有都返回true的时候,才返回true。

题解

class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right) {
        if (left == NULL && right != NULL) return false;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right == NULL) return true;
        else if (left->val != right->val) return false;
        else return compare(left->left, right->right) && compare(left->right, right->left);
    }
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        return compare(root->left, root->right);
    }
};
class Solution:
    def compare(self, left, right):
        if left == None and right !=  None: return False
        elif left != None and right ==  None: return False
        elif left == None and right == None: return True
        elif left.val != right.val: return False
        else: return self.compare(left.left, right.right) and self.compare(left.right, right.left)


    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        return self.compare(root.left, root.right)

反思

二叉树的题目确定遍历顺序非常重要。

104.二叉树的最大深度

题目链接

104.二叉树的最大深度

思想

在这里插入图片描述
区分深度和高度
深度:二叉树里任意一个节点到根节点的距离——前序
高度:二叉树任意一个节点到叶子节点的距离——后序
一般题解都是后序遍历,因为根节点的高度就是最大深度。真正求深度应该用前序遍历。
本题还是求的根节点的高度(也就是最大深度),所以用的后序遍历
递归三部曲:

  1. 确定递归函数的参数和返回值
  2. 确定终止条件 遇到空了 高度应该是0
  3. 逻辑:
    递归左
    递归右
    中:1 + max

题解

class Solution {
public:
    int getdepth(TreeNode* node) {
        if (node == NULL) return 0;
        // 后序遍历
        int leftdepth = getdepth(node->left);
        int rightdepth = getdepth(node->right);
        return 1 + max(leftdepth, rightdepth);
    }
    int maxDepth(TreeNode* root) {
        return getdepth(root);
    }
};
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0;
        return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))

反思

要理解本题的本质是后序遍历,上面题解给出的精简解法掩盖了后序遍历的本质,其实实际上也是后序遍历。

111.二叉树的最小深度

题目链接

111.二叉树的最小深度

思想

**二叉树的最小深度:**根节点到叶子节点的最小距离。
和上一题有点类似,只是把取最大值变为取最小值,上一题用后序求了高度,本题也可以用后序求高度,得到深度。其实前序遍历才是个求深度过程。
写前序遍历的代码比后序的稍微麻烦点,前序代码见代码随想录。
递归三部曲:

  1. 确定返回值和参数
  2. 确定终止条件:node==NULL 返回0
  3. 递归逻辑:左右中

    注意这里写中间的逻辑的时候不能直接返回min+1,比如上图,根据题目给出的定义,最小深度应该是3。也就是说要处理当孩子有NULL的情况。

题解

class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = getDepth(node->left);
        int rightDepth = getDepth(node->right);

        if (node->left != NULL && node->right == NULL) return 1 + leftDepth;
        if (node->left == NULL && node->right != NULL) return 1 + rightDepth;
        return 1 + min(leftDepth, rightDepth);
    }
    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if root==None:
            return 0
        if root.left == None and root.right != None:
            return 1 + self.minDepth(root.right)
        if root.left != None and root.right == None:
            return 1 + self.minDepth(root.left)
        return 1 + min(self.minDepth(root.left), self.minDepth(root.right))

反思

注意不能直接返回min+1,有埋伏!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值