LeetCode刷题复盘笔记:打爆二叉树(续一)(翻转,N叉树前后序遍历,对称二叉树)

在此非常感谢“代码随想录”的通俗易懂的总结,昨天一口气打了六个,感觉意犹未尽,今天继续打,怎么说,先凑10个吧!

(致敬叶师傅和李小龙)

在这里插入图片描述

“我不害怕曾经练过一万种踢法的人,但我害怕一种踢法练过一万次的人”(by 叶师傅的徒弟Bruce Lee)
在这里插入图片描述

今天是2021年3月15日,昨天龙抬头和白色情人节的“双节”刚刚过去,第一次一口气刷了6道中等难度Leetcode题。今天又迎来了“3.15——国际消费者权益日”,那就今天继续再打4道,怎么说都要先凑齐10个!加油,冲冲冲!

一、前言:

简单问题可以不简单,正如李小龙所说,把一件简单事情做到极致,把每一道刷透理解透,注重质量,让自己变得无可替代,是一件非常不简单的事情!

二、具体题目

题目1:226. 翻转二叉树

这道题目背后有一个让程序员心酸的故事,据说谷歌90%的工程师使用的软件Homebrew的作者Max Howell,就是因为面试谷歌时没有在白板上写出翻转二叉树这道题,最后被Google拒绝了。

题目描述:
翻转一棵二叉树。
示例:
在这里插入图片描述

「这道题目使用前序遍历、后序遍历以及层序遍历都可以,但只是使用单纯中序遍历不行,因为中序遍历会把某些节点的左右孩子翻转了两次,但是可以把中序遍历稍微改动一下即可!」

C++代码

方法一、广度优先遍历——层序遍历

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;++i){
                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;
    }
};

方法二、深度优先遍历——前序遍历(递归)

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 {
public:
    TreeNode* invertTree(TreeNode* root) {
        // if(root==NULL) return root; 
        stack<TreeNode*> st;
        if(root) 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;
    }
};

方法四、中序遍历递归改编版

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        invertTree(root->left);         // 左
        swap(root->left, root->right);  // 中
        invertTree(root->left);         // 注意 这里依然要遍历左孩子,因为中间节点已经翻转了
        return root;
    }
};

题目2:589. N 叉树的前序遍历

题目描述:
给定一个 N 叉树,返回其节点值的前序遍历 。

N叉树在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

进阶:
递归法很简单,你可以使用迭代法完成此题吗?

示例 1:

在这里插入图片描述

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

在这里插入图片描述

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10]

C++代码:

方法一、递归解法

class Solution {
public:
    vector<int> result;
    void traversal(Node* root){
        if(root==NULL) return;
        result.push_back(root->val);
        int size=root->children.size();
        for(int i=0;i<size;++i){
            traversal(root->children[i]);
        }
    }
    vector<int> preorder(Node* root) {
        traversal(root);
        return result;
    }
};

方法二、迭代解法

class Solution {
public:
    vector<int> preorder(Node* root) {
        vector<int> result;
        if(root==NULL) return result;
        stack<Node*> st; 
        st.push(root);
        while(!st.empty()){
            Node* cur=st.top();
            st.pop();
            result.push_back(cur->val);
            int size=cur->children.size();
            for(int i=size-1;i>=0;--i){
                if(cur->children[i]) st.push(cur->children[i]);
            }        
        }
        return result;
    }
};

题目3:590. N 叉树的后序遍历

题目描述:
给定一个 N 叉树,返回其节点值的后序遍历 。

N叉树在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

进阶:
递归法很简单,你可以使用迭代法完成此题吗?

示例 1:
在这里插入图片描述

输入:root = [1,null,3,2,4,null,5,6]
输出:[5,6,3,2,4,1]
示例 2:
在这里插入图片描述
输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[2,6,14,11,7,3,12,8,4,13,9,10,5,1]

C++代码:

方法一、递归方法

class Solution {
public:
    vector<int> result;
    void traversal(Node* root){
        if(root==NULL) return;
        int size=root->children.size();
        for(int i=0;i<size;++i){
            traversal(root->children[i]);
        }
        result.push_back(root->val);
    }
    vector<int> postorder(Node* root) {
        traversal(root);
        return result;
    }
};

方法二、迭代方法

class Solution {
public:
    vector<int> postorder(Node* root) {
        vector<int> result;
        if(root==NULL) return result;
        stack<Node*> st;
        st.push(root);
        while(!st.empty()){
            Node* cur=st.top();
            st.pop();
            result.push_back(cur->val);
            int size=cur->children.size();
            for(int i=0;i<size;++i){
                st.push(cur->children[i]);
            }
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

题目4:101. 对称二叉树

题目描述:
给定一个二叉树,检查它是否是镜像对称的。
在这里插入图片描述
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?

C++代码:

用三种方法刷透就完事!(当然队列和栈只是容器不同,而原理都是迭代!)
方法一、递归方法

class Solution {
public:
    bool compare(TreeNode* left,TreeNode* right){
        if(!left && !right) return true;//排除根左右全是空节点情况
        else if(!left || !right ||left->val!=right->val) return false;
        else return (compare(left->right,right->left) && compare(left->left,right->right));
    }
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        else return compare(root->left,root->right);
    }
};

方法二、迭代之队列方法

引用一下代码随想录的动图便于理解:
在这里插入图片描述

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) 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 && !right) continue;
            else if(!left || !right || left->val!=right->val) return false;
            else{
                que.push(left->left);
                que.push(right->right);
                que.push(left->right);
                que.push(right->left);
            }
        }
        return true;
    }
};

方法三、迭代之栈方法

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        stack<TreeNode*> st;
        st.push(root->right);
        st.push(root->left);
        while(!st.empty()){
            TreeNode* left=st.top();
            st.pop();
            TreeNode* right=st.top();
            st.pop();
            if(!left && !right) continue;
            else if(!left || !right || left->val!=right->val) return false;
            else{
                st.push(left->left);
                st.push(right->right);
                st.push(left->right);
                st.push(right->left);
            }
        }
        return true;
    }
};

代码随想录链接

总结

二叉树

针对二叉树的问题,解题之前一定要想清楚究竟是前中后序遍历,还是层序遍历。

「二叉树解题的大忌就是自己稀里糊涂的过了,但是也不知道自己是怎么遍历的。」

对于二叉树节点的定义,C++代码如下:

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

对于这个定义中TreeNode(int x) : val(x), left(NULL), right(NULL) {} 这一行我开始也有些不太懂,后来才知道这是构造函数。
构造函数也可以不写,但是new一个新的节点的时候就比较麻烦。

例如有构造函数,定义初始值为9的节点:

TreeNode* a = new TreeNode(9);

没有构造函数的话就要这么写:(非常麻烦不方便!)

TreeNode* a = new TreeNode(); 
a->val = 9; 
a->left = NULL;
a->right = NULL;

欢迎大家扫码关注本人公众号:编程复盘与思考随笔

(关注后可以免费获得本人在csdn发布的资源源码)

公众号主要记录编程和刷题时的总结复盘笔记和心得!并且分享读书、工作、生活中的一些思考感悟!在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Al资料站与复盘笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值