代码随想录算法训练营第15天|102.二叉树层序遍历、层序遍历类型题目、226.翻转二叉树、101.对称二叉树

102.二叉树层序遍历

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

用队列实现,用NULL隔开各层元素。

二、学习文章后收获

逐层遍历:
对于每层结点,提前统计当前queue中的元素个数size,然后用for循环遍历这size个元素。
注:要事先记录下queue的size,因为que.size()在之后的过程中会改变!

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        TreeNode* cur = NULL;
        vector<vector<int>> result;
        vector<int> v;
        if(root) que.push(root);
        while(!que.empty()){
            int size = que.size(); //要事先记录下que的size,因为que.size()在之后的过程中会改变!
            v.clear();
            for(int i = 0;i < size;i++){
                cur = que.front();
                que.pop();
                v.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(v);
        }
        return result;
    }
};

三、过程中遇到的问题

1.pop()操作没有返回值

stack和queue的pop()都没有返回值!
stack.top()是栈顶元素
queue.front()是队头元素

(层序遍历的递归形式还没看)


层序遍历其他题目(未更完)


226. 翻转二叉树

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

遍历+左右孩子互换。
遍历尝试了“层序”和“迭代统一写法的中序”。
没有想到递归法。

二、学习文章后收获

1.方法:

  • 整体思路:遍历+左右节点左右孩子互换
  • 适用的遍历方法:
    • 递归:递归的后序、递归的先序都可,但是递归的中序不可(除非稍作修改)。
    • 非递归:层序可以,迭代的先序、后序都可以,中序的迭代统一写法可以。

2.递归代码

  • 递归,先序
class Solution {
public:
    void swap(TreeNode* t){
        TreeNode* temp;
        temp = t->left;
        t->left = t->right;
        t->right = temp;
    }
    TreeNode* invertTree(TreeNode* root) {
        if(root == NULL) return root;
        swap(root);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};
  • 递归,中序
class Solution {
public:
    void swap(TreeNode* t){
        TreeNode* temp;
        temp = t->left;
        t->left = t->right;
        t->right = temp;
    }
    TreeNode* invertTree(TreeNode* root) {
        if(root == NULL) return root;
        invertTree(root->left);  
        swap(root);
        invertTree(root->left); //注意这里!
        return root;
    }
};

101. 对称二叉树

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

方法一:

(我自己的方法)
层序遍历,并用deque来记录每层节点,然后判断deque是否对称。
(注意:对从deque中弹出的元素,如果左/右孩子为NULL也需要记录在deque里!但如果从deque中直接弹出NULL,不用压入两个NULL,否则循环无法退出!)

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        deque<TreeNode*> deq;
        TreeNode* cur;
        if(root){
            deq.push_front(root->left);
            deq.push_back(root->right);
        }
        while(!deq.empty()){
            int size = deq.size();
            deque<TreeNode*>::iterator it_front = deq.begin();
            deque<TreeNode*>::iterator it_back = deq.end()-1;
            //比较deque的前半段和后半段是否相同
            for(int i = 0;i < size/2;i++){
                if(*it_front && *it_back && (*it_front)->val == (*it_back)->val){
                    it_back--;
                    it_front++;
                    continue;
                }
                else if(*it_back == NULL && *it_front == NULL){
                    it_back--;
                    it_front++;
                    continue;
                }
                else{
                    return false;
                }
            }
            //把deque里的数据更新成下一层的节点。
            for(int i = 0;i < size;i++){
                cur = deq.front();
                deq.pop_front();
                if(cur){
                    deq.push_back(cur->left);
                    deq.push_back(cur->right);
                }
            }
        }
        return true;
    }
};

二、学习文章后收获

方法二:递归法

  • 传递参数和返回值:参数是要比较是否对称的两个节点,返回值是比较的结果
  • 本层内需要做的处理:针对这两个节点,判断是否对称(①如果两节点全空,则返回true。②如果两节点全不空,而且val相等,则继续检查对应的“内侧两节点”和“外侧两节点”是否对称。③除此之外,都不对称,都返回false。)
  • 返回条件:上一点已说明。
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root) return myCompare(root->left,root->right);
        else return true;
    }
    bool myCompare(TreeNode* node1,TreeNode* node2){
        if(node1 == NULL && node2 == NULL) return true;
        else if(node1 != NULL && node2 != NULL && node1->val == node2->val){
            bool compareInside = myCompare(node1->right,node2->left);
            bool compareOutside = myCompare(node1->left,node2->right);
            return compareInside && compareOutside;
        }
        else return false;
    }
};

方法三:队列+迭代法

其实方法三和方法四(队列和栈)本质上都是通过可存储的数据结构来暂存待处理的节点,主要是要确定入队列/栈的顺序,你维护的数据结构要让之后每次弹出的两个相邻元素都是“对称位置”上的元素

注:如果孩子有NULL,也会入队/栈。但是NULL的孩子NULL不会再入队/栈了。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> q;
        TreeNode* node1 = NULL, *node2 = NULL;
        if(root){
            q.push(root->left);
            q.push(root->right);
        }
        while( !q.empty() ){
            node1 = q.front();
            q.pop();
            node2 = q.front();
            q.pop();
            if(node1 == NULL && node2 == NULL) continue;
            else if(node1 == NULL && node2 != NULL) return false;
            else if(node1 != NULL && node2 == NULL) return false;
            else if(node1 != NULL && node2 != NULL && node1->val != node2->val) return false;
            else if(node1 != NULL && node2 != NULL && node1->val == node2->val){
                q.push(node1->left);
                q.push(node2->right);
                q.push(node1->right);
                q.push(node2->left);
            }
        }
        return true;
    }
};

方法四:栈+迭代法

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

三、过程中遇到的问题

1.运算符优先级

->优先级巨高,高于*
错误写法:*iterator->val
正确写法:(*iterator)->val
报错信息:
Line 27: Char 73: error: member reference base type ‘TreeNode *’ is not a structure or union
27 | if(*it_front && *it_back && (*it_front)->val == *it_back->val){
| ~~~^
1 error generated.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值