代码随想录第十二天:反转二叉树、对称二叉树、最大深度、最小深度

1.反转二叉树

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:听说一位巨佬面Google被拒了,因为没写出翻转二叉树 | LeetCode:226.翻转二叉树_哔哩哔哩_bilibili

本题的基本思想是依次遍历所有结点,然后一一交换每个结点的左右子树。

但是不是所有遍历方法都可以,中序遍历会让左子树被交换两次。

涉及到遍历就有三种方法实现:递归、迭代和层序。

递归法:

首先确定三要素:

1.返回值与参数:本题每次递归不需要输出,因此返回值是空。参数是树结点指针。

2.终止条件:在遇到空节点时中止。

3.单层循环的逻辑:只要简单交换左右结点即可,可以使用swap()函数实现。

迭代法:

与遍历的代码类似,使用栈来实现。每次交换完左右孩子再将其入栈。

层序遍历:

同样与遍历类似,使用队列实现。每次交换完左右还在再将其入队。

代码如下:

// 递归法(前序)
void invert(TreeNode* root){
    if (root == nullptr)
        return;
    swap(root->left, root->right);
    invert(root->left);
    invert(root->right);
}

TreeNode* invertTree(TreeNode* root) {
    invert(root);
    return root;
}

// 迭代法(前序)
TreeNode* invertTree1(TreeNode* root) {
    if (root == nullptr) return root;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()){
        TreeNode* cur = st.top();
        st.pop();
        swap(cur->left, cur->right);
        if (cur->right) st.push(cur->right);
        if (cur->left) st.push(cur->left);
    }
    return root;
}

// 层序遍历
TreeNode* invertTree2(TreeNode* root) {
    if (root == nullptr) return root;
    queue<TreeNode*> que;
    que.push(root);
    while (!que.empty()){
        TreeNode* cur = que.front();
        que.pop();
        swap(cur->left, cur->right);
        if (cur->left) que.push(cur->left);
        if (cur->right) que.push(cur->right);
    }
    return root;
}

2.对称二叉树

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:新学期要从学习二叉树开始! | LeetCode:101. 对称二叉树_哔哩哔哩_bilibili

本题要确定好对称的比较逻辑:外侧与外侧比(左结点的左孩子和右结点的右孩子比),内侧与内侧比(左结点的右孩子和右结点的左孩子比)。

递归法:

三要素

1.返回值与参数:本题每次递归需要返回左右子树是否对称,返回值为bool。需要传入左右子树比较,参数为两个数结点指针。

2.终止条件:本题终止条件较多,就是什么情况下可以判断已经不对称了。有以下几种情况:左空右不空、左不空右空、左右数值不相等,这些情况确定已经不对称了,可以返回false。而左右都为空可以确定是对称的,返回true。最后只剩下左右数值相等的情况,因为还要判断子树的情况。

3.单层逻辑:单层逻辑仅需判断左右数值相等的情况。根据比较逻辑依次对:左结点的左子树和右结点的右子树、左结点的右子树和右结点的左子树。只有当他们都对称时,才返回true。否则返回false。

代码如下:

bool compare(TreeNode* A, TreeNode* B){
    if (A == nullptr && B != nullptr) return false;
    else if (A != nullptr && B == nullptr) return false;
    else if (A == nullptr && B == nullptr) return true;
    else if(A->val != B->val) return false;
    else{
        bool com1 = compare(A->left, B->right);
        bool com2 = compare(A->right, B->left);
        return com1 && com2;
    }
}

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

3.最大深度

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | LeetCode:104.二叉树的最大深度_哔哩哔哩_bilibili

深度是某一结点到根结点的路径长度,最大深度就是最远的叶子结点到根结点的路径长度,也就是二叉树根结点的高度。而求高度要使用后序遍历(求深度不知道最远的叶子结点在哪,求高度可以从根节点开始,所以求高度代替深度)。

递归法:

三要素

1.返回值与参数:需要返回子树的高度,返回值为int。参数为树结点指针。

2.终止条件:遇到空节点停止,返回0;

3.单层逻辑:后序遍历,先处理左右子树高度。然后取最大值+1为该树的高度。

层序遍历:

求深度是层序遍历的拿手绝活,每遍历一层让深度+1即可。

代码如下:

// 递归
int getDepth(TreeNode* root){
    if (root == nullptr)
        return 0;
    int leftDepth = getDepth1(root->left);
    int rightDepth = getDepth1(root->right);
    int Depth = 1 + max(leftDepth, rightDepth);
    return Depth;
}

int maxDepth(TreeNode* root){
    return getDepth1(root);
}

// 层序
int maxDepth(TreeNode* root){
    if (root == nullptr) return 0;
    queue<TreeNode*> que;
    que.push(root);
    int depth = 0;
    while (!que.empty()){
        int size = que.size();
        while (size--){
            TreeNode* cur = que.front();
            que.pop();
            if (cur->left) que.push(cur->left);
            if (cur->right) que.push(cur->right);
        }
        depth++;
    }
    return depth;
}

4.最小深度

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度_哔哩哔哩_bilibili

本题看起来与最大深度相似,但是要注意最小深度指的是叶子结点的最小深度(最大深度一定是叶子节点处,所以不用额外注意),即该结点左右孩子为空。

递归法:

三要素

1.返回值与参数:每次递归要返回树的最小深度,返回值为int。参数为树结点指针。

2.终止条件:遇到空节点终止。

3.单层逻辑:求深度时要注意他是否是叶子结点,不能简单取左右子树的最小值。如果该结点只有右子树,最小深度就是右子树最小深度+1,反之就是左子树最小深度+1。如果左右子树都存在,再取他们的最小值。

层序遍历:

同样是层序遍历的绝活,只要在队列中碰到左右孩子都为空的结点时返回当前深度即可。

代码如下:

// 递归法
int getDepth(TreeNode* root){
    if (root == nullptr)
        return 0;
    if (root->left == nullptr && root->right != nullptr)
        return 1 + getDepth2(root->right);
    else if (root->left != nullptr && root->right == nullptr)
        return 1 + getDepth2(root->left);
    else
        return 1 + min(getDepth2(root->left), getDepth2(root->right));
}

int minDepth1(TreeNode* root){
    return getDepth2(root);
}

// 层序遍历
int minDepth(TreeNode* root){
    if (root == nullptr) return 0;
    queue<TreeNode*> que;
    que.push(root);
    int depth = 1;
    while (!que.empty()){
        int size = que.size();
        while (size--){
            TreeNode* cur = que.front();
            que.pop();
            if (cur->left == nullptr && cur->right == nullptr)
                return depth;
            if (cur->left) que.push(cur->left);
            if (cur->right) que.push(cur->right);
        }
        depth++;
    }
    return depth;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值