代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2

10道层序遍历

 关于层序遍历的recursion递归法

!!!尽管层序遍历的recursion方法能够生成按层级组织的输出,但它的遍历方式实际上是dfs

代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2_第1张图片

在开头总结下这10道题:

代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2_第2张图片

基础模板:102,107,199,429

适合用bfs迭代,不推荐用dfs/递归(因为要同层内操作):637,515,116,117

bfs dfs都可:找深度 104, 111 (这一章是层次遍历,我们找深度的题都可以直接当层次遍历的模板题,之后博客还会详细讨论“深度”题型)

1. 102 基本款层序遍历

层序遍历-迭代法

注意:用固定大小size来遍历

    vector> levelOrder(TreeNode* root) {

        vector> res;
        queue myq;
        if(root!=nullptr) myq.push(root);
        while(!myq.empty()){
            int size=myq.size();
            vector vec;
            //此处一定要用固定大小size,因为不断操作myq,用queue.size()会变
            for(int i=0;ival);
                myq.pop();
                if(node->left!=nullptr) myq.push(node->left);
                if(node->right!=nullptr) myq.push(node->right);
            }
            res.push_back(vec);
        }
        return res;
    }

层序遍历-递归法

易错:传入的变量到底是var还是ref

如何想明白:如果depth传的是ref的话,if(node->left!=nullptr)order(node->left,depth+1,res);这个执行完到下一句right那里,depth就会变,但不能让他变

void order(TreeNode* node, int depth, vector> &res){
        //depth 不應該傳入ref很重要,因爲遞歸的歸 return
        //比如left做完回來的時候,depth不應該變
        if(node==nullptr)return;
        
        if(res.size()==depth)res.push_back(vector());
            
        res[depth].push_back(node->val);
           
        
        if(node->left!=nullptr)order(node->left,depth+1,res);
        if(node->right!=nullptr)order(node->right,depth+1,res);
    }
    vector> levelOrder(TreeNode* root) {

        vector> res;
        int depth=0;
        order(root, depth, res);
        return res;
    }

代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2_第3张图片

 以上是探讨dfs&bfs实现的区别

2. 107 层序遍历从最下层开始 易变体: 迭代ok 递归ok 都是最基本的+vec反一下就行;

    vector> levelOrderBottom(TreeNode* root) {
        //想到幾種方法:1 放入 stack來反過來
        //2 用雙指針把vec 做reverse
        //3 用庫函數做reverse
    vector> res;
    queue myq;
    if(root!=nullptr) myq.push(root);
    TreeNode *node;
    while(!myq.empty()){
        int size=myq.size();
        vector vec;
        for(int i=0;ival);
            myq.pop();
            if(node->left!=nullptr) myq.push(node->left);
            if(node->right!=nullptr) myq.push(node->right);
        }
        res.push_back(vec);
    }
    //reverse(res.begin(),res.end());
    int i=0; int j=res.size()-1;
    while(i

3. 199 层序右视图 易变体,迭代ok:pushback vec改成if(i==size-1) res.push_back(node->val); 即可

    vector rightSideView(TreeNode* root) {
        vector res;
        queuemyq;
        TreeNode* node;
        if(root!=nullptr) myq.push(root);
        while(!myq.empty()){
            int size=myq.size();
            for(int i=0;ileft!=nullptr) myq.push(node->left);
                if(node->right!=nullptr) myq.push(node->right);
                if(i==size-1) res.push_back(node->val);
            }
        }
        return res;
        
    }

递归ok

void traverse(TreeNode* node, int depth, vector &res){
        if(node==nullptr) return;
        if(depth==res.size()) res.push_back(0);
        res[depth]=node->val;
        //关键是前面这两行,一开始觉得很难找到一层最后一个
        //后来发现每个新的来了覆盖就行
        if(node->left!=nullptr) traverse(node->left, depth+1, res);
        if(node->right!=nullptr) traverse(node->right, depth+1, res);
        
    }
    vector rightSideView(TreeNode* root) {
        vector res;
        traverse(root, 0, res);
        return res;
        
    }

4. 637 每层的平均值,易变体,迭代ok

易错需注意:有运算和大的加时,记得type:double、long,反正不能用int了,我这个方面意识薄弱

    vector averageOfLevels(TreeNode* root) {
        vector res;
        queuemyq;
        TreeNode* node;
        
        if(root!=nullptr) myq.push(root);
        while(!myq.empty()){
            int size=myq.size();
            long sum=0;
            double avg=0;
            for(int i=0;ileft!=nullptr) myq.push(node->left);
                if(node->right!=nullptr) myq.push(node->right);
                sum+=node->val;
            }
            avg=(double)sum/size;
            res.push_back(avg);
        }
        return res;
    }

递归会很复杂,对同层元素之间操作的(求平均值,找最大/小值,放入next)都不适合用recursion-dfs做,会非常复杂。下面是gpt写的,过了,我是懒得写了,复杂而且不适合

void averageOfLevels(TreeNode* node, int depth, vector& sums, vector& counts) {
    if (node == nullptr) return;

    if (depth >= sums.size()) {
        sums.push_back(node->val);
        counts.push_back(1);
    } else {
        sums[depth] += node->val;
        counts[depth] += 1;
    }

    averageOfLevels(node->left, depth + 1, sums, counts);
    averageOfLevels(node->right, depth + 1, sums, counts);
}

vector averageOfLevels(TreeNode* root) {
    vector sums;
    vector counts;
    averageOfLevels(root, 0, sums, counts);

    vector averages;
    for (int i = 0; i < sums.size(); ++i) {
        averages.push_back(static_cast(sums[i]) / counts[i]);
    }
    
    return averages;
}

代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2_第4张图片

5.  429 N叉树的层序遍历,易变体,递归懒得写了,下面是迭代,但思路都是该做左右的时候改成一个for loop做n个崽

vector> levelOrder(Node* root) {
        vector> res;
        queue myq;
        Node* node;
        if(root!=nullptr) myq.push(root);
        while(!myq.empty()){
            
            int size=myq.size();
            vector vec;
            for(int i=0;ival);
                vector clist=node->children;
                for(auto &ele:clist){
                    myq.push(ele);
                }
                
            }
            res.push_back(vec);
        }
        return res;
    }

6. 515.在每个树行中找最大值,和取每层最右像

我写的递归,但逻辑上讲不适合递归,虽然也是好写的

void order(int depth, vector &res, TreeNode* node){
        if(node==nullptr) return;

        // 当这一层还没有值时,将节点的值添加到结果中
        if(res.size() == depth)  res.push_back(node->val);
        // 否则,更新这一层的最大值
        else res[depth] = std::max(res[depth], node->val);
    
        if(node->left!=nullptr) order(depth+1, res, node->left);
        if(node->right!=nullptr) order(depth+1, res, node->right);
    }

    vector largestValues(TreeNode* root) {
        vector res;
        int depth=0;
        order(depth, res, root);
        return res;
    }

代码随想录的迭代,就是基本迭代加了一点点取max

vector largestValues(TreeNode* root) {
        queue que;
        if (root != NULL) que.push(root);
        vector result;
        while (!que.empty()) {
            int size = que.size();
            int maxValue = INT_MIN; // 取每一层的最大值
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                maxValue = node->val > maxValue ? node->val : maxValue;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(maxValue); // 把最大值放进数组
        }
        return result;
    }

7.8. 116.填充每个节点的下一个右侧节点指针,117 II 两题没差

这个不完全算简单变体,我做的时候遇到点麻烦:原来是这么写的

代码随想录算法训练营第15天 | 二叉树part02:●层序遍历和10道题● 226.翻转二叉树 ● 101.对称二叉树 2_第5张图片

 修改正确后:

Node* connect(Node* root) {
        queue myq;
        
        Node* node;
        Node* prev=nullptr;

        if(root!=nullptr) myq.push(root);

        while(!myq.empty()){
            int size=myq.size();
            for(int i=0;i0) prev->next=node;
                if(node->left!=nullptr) myq.push(node->left);
                if(node->right!=nullptr) myq.push(node->right);
                prev=node;
            }
            node->next=nullptr;
        }
        return root;
    } 

这题也不适合递归做,所以没做递归

做深度,用recursion ,iteration都行,问题不大

9. 104 最大深度

递归我的

int get_depth(TreeNode* node){
        if(node==nullptr) return 0;
        int left_d=0; int right_d=0;
        if(node->left!=nullptr) left_d=get_depth(node->left);
        if(node->right!=nullptr) right_d=get_depth(node->right);
        return std::max(left_d,right_d)+1;

    }
    int maxDepth(TreeNode* root) {
        return get_depth(root);
    }
void order(int depth, TreeNode * node, int &max){
        if(node==nullptr) return;
        max=std::max(max,depth);
        if(node->left!=nullptr) order(depth+1,node->left,max);
        if(node->right!=nullptr) order(depth+1,node->right,max);

    }
    int maxDepth(TreeNode* root) {
        int depth=1;
        int max=0;
        order(depth, root, max);
        return max;
    }

递归简洁版

int maxDepth(TreeNode* root) {
    if(root == nullptr)
        return 0;
    else
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}

迭代(基础版迭代加个depth就行)

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

10. 111 最小深度

我的递归(基础款不用动脑改)

void order(TreeNode * node, int &min, int depth){
        if(node==nullptr){
            min=0;
            return;
        }
        if(node->left==nullptr && node->right==nullptr){
            min=std::min(min,depth);
        }
        if(node->left!=nullptr) order(node->left,min,depth+1);
        if(node->right!=nullptr) order(node->right,min,depth+1);


    }
    int minDepth(TreeNode* root) {
        int depth=1;
        int min=INT_MAX;
        
        order(root, min, depth );
        return min;
    }

迭代gpt:走到第一个leaf node就可以结束啦!!会更有效率

int minDepth(TreeNode* root) {
    if(root == nullptr)
        return 0;
    queue que;
    que.push(root);
    int depth = 0;
    while(!que.empty()){
        int size = que.size();
        depth++;
        for(int i = 0; i < size; i++){
            TreeNode* node = que.front();
            que.pop();
            if(node->left == nullptr && node->right == nullptr)
                return depth;
            if(node->left) que.push(node->left);
            if(node->right) que.push(node->right);
        }
    }
    return depth;
}

226.翻转二叉树

方法包括:

dfs recursion:前后就是套模板加swap,中序需要两次left中间夹swap

void order(TreeNode * node){
        if(node==nullptr) return;
        
        //这是很特殊的中序,swap后左右换了所以再一次左
        if(node->left!=nullptr) order(node->left);
        swap(node->left,node->right);
        if(node->left!=nullptr) order(node->left);

        //前序和后续就是普通:like this
        //if(node->left!=nullptr) order(node->left);
        //if(node->right!=nullptr) order(node->right);
        //swap(node->left,node->right);
        
    }

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

dfs iteration:直接套统一迭代的模板,加一句swap

TreeNode* invertTree(TreeNode* root) {
        stack st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                st.push(node);                          // 中
                st.push(NULL);
            } else {
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left, node->right);          // 节点处理逻辑
            }
        }
        return root;
    }

bfs iteration:套层序遍历的模板 

TreeNode* invertTree(TreeNode* root) {
        queue que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                swap(node->left, node->right); 
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }

101 对称二叉树2

第一次做想了好久

bool isSymmetric(TreeNode* root) {
        queue myq1;
        queue myq2;
        if(root!=nullptr){
            myq1.push(root);
            myq2.push(root);
        }
        TreeNode *node1, *node2;

        while(!(myq1.empty() ||myq2.empty())){
            int size1=myq1.size();
            int size2=myq2.size();
            if(size1!=size2) return false;

            for(int i=0;ival!=node2->val) return false;

                if(node1->left!=nullptr){
                    if(node2->right==nullptr) return false;
                    myq1.push(node1->left);
                }
                if(node1->right!=nullptr){
                    if(node2->left==nullptr) return false;
                    myq1.push(node1->right);

                }
                
                if(node2->right!=nullptr){
                    if(node1->left==nullptr) return false;
                    myq2.push(node2->right);

                }
                if(node2->left!=nullptr){
                    if(node1->right==nullptr) return false;
                    myq2.push(node2->left);
                }

            }
            
        }
        if(!(myq1.empty()&&myq2.empty())) return false;
        return true;
    }

自己想的过于复杂,参考答案很简单的:

关键是:return compare(left->left,right->right)&&compare(left->right,right->left);

bool compare(TreeNode* left, TreeNode* right){
        if(left==nullptr && right==nullptr) return true;
        if(left==nullptr) return false;
        if(right==nullptr) return false;
        if(left->val!=right->val) return false;

        return compare(left->left,right->right)&&compare(left->right,right->left);


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

    }

你可能感兴趣的:(代码随想录一刷,算法,c++)