letcode 分类练习 树的遍历

news2025/1/1 8:54:49

letcode 分类练习 树的遍历

  • 树的构建
  • 递归遍历
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 迭代遍历
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 层序遍历
    • 层序遍历可以解决的问题
      • 107. 二叉树的层序遍历 II
      • 199. 二叉树的右视图
      • 637. 二叉树的层平均值
      • 429. N 叉树的层序遍历
      • 515.在每个树行中找最大值
      • 116.填充每个节点的下一个右侧节点指针
      • 117.填充每个节点的下一个右侧节点指针II
      • 104.二叉树的最大深度
      • 111.二叉树的最小深度

树的构建

输入数组:[8, 3, 10, 1, 6, null, 14, null, null, 4, 7, 13]

#include <iostream>
#include <vector>
#include <queue>
#include <memory>

using namespace std;

// 定义二叉树节点结构
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 根据向量数组构建二叉树
TreeNode* constructBinaryTree(const vector<int*>& nums) {
    if (nums.empty() || !nums[0]) {
        return nullptr;
    }

    // 使用队列进行层序遍历构建树
    queue<TreeNode*> q;
    TreeNode* root = new TreeNode(*nums[0]);
    q.push(root);
    int i = 1;

    while (!q.empty() && i < nums.size()) {
        TreeNode* current = q.front();
        q.pop();

        // 构建左子节点
        if (i < nums.size() && nums[i]) {
            current->left = new TreeNode(*nums[i]);
            q.push(current->left);
        }
        i++;

        // 构建右子节点
        if (i < nums.size() && nums[i]) {
            current->right = new TreeNode(*nums[i]);
            q.push(current->right);
        }
        i++;
    }

    return root;
}

递归遍历

前序遍历

class Solution {
public:
    vector<int> result;
    void dfs(TreeNode* root){
        if(!root) return;
        result.push_back(root->val);
        if(root -> left)dfs(root -> left);
        if(root -> right)dfs(root-> right);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        dfs(root);
        return result;
    }
};

中序遍历

class Solution {
public:
    vector<int> result;
    void dfs(TreeNode* root){
        if(!root) return;
        if(root->left)dfs(root->left);
        result.push_back(root -> val);
        if(root->right)dfs(root->right);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        dfs(root);
        return result;
    }
};

后序遍历

class Solution {
public:
    vector<int> result;
    void dfs(TreeNode* root){
        if(!root) return;
        if(root->left)dfs(root->left);
        if(root->right)dfs(root->right);
        result.push_back(root -> val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        dfs(root);
        return result;
    }
};

迭代遍历

前序遍历

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> result;
        if(!root)return result;
        while(root || !s.empty()){
            while(root){
                s.push(root);
                // 这里while一直向左就开始收集
                result.push_back(root->val);
                root = root -> left;
            }
            TreeNode* node = s.top();
            s.pop();
            root = node -> right;
        }
        return result;
    }
};

中序遍历

在这里插入图片描述

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> result;
        if(!root)return result;
        while(root || !s.empty()){
            while(root){
                s.push(root);
                root = root -> left;
            }
            TreeNode* node = s.top();
            s.pop();
            // 弹栈的时候才收集
            result.push_back(node->val);
            root = node -> right;
        }
        return result;
    }
};

后序遍历


后序遍历的迭代方式有区别,就是弹栈后,不是收集,而是判断它的右孩子节点,如果右孩子为空,说明它是叶子节点,这个时候我们收集到result里,并且把这个标记成前驱节点,root再置为空。如果右孩子不为空,我们要像访问左孩子这样继续遍历。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> result;
        if(!root) return result;
        TreeNode* prev;
        while(root || !s.empty()){
            while(root){
                s.push(root);
                root = root -> left;
            }
            TreeNode* root = s.top();
            s.pop();
            if(root -> right == nullptr && root != prev){
                result.push_back(root -> val);
                prev = root;
                root = root -> right;
            }else{
                s.push(root);
                root = root -> right;
            }
        }
        return result;
    }
};

层序遍历

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*>q;
        vector<vector<int>> result;
        if(!root)return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            vector<int> tmp;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                tmp.push_back(node -> val);
                if(node->left)q.push(node->left);
                if(node->right)q.push(node->right);
            }
            result.push_back(tmp);
        }
        return result;

    }
};

层序遍历可以解决的问题

107. 二叉树的层序遍历 II

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*>q;
        vector<vector<int>> result;
        if(!root)return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            vector<int> tmp;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                tmp.push_back(node -> val);
                if(node->left)q.push(node->left);
                if(node->right)q.push(node->right);
            }
            result.push_back(tmp);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

199. 二叉树的右视图

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*>q;
        vector<int> result;
        if(!root)return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            vector<int> tmp;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                if(i==k-1) result.push_back(node -> val);
                if(node->left)q.push(node->left);
                if(node->right)q.push(node->right);
            }
        }
        return result;
    }
};

637. 二叉树的层平均值

在这里插入图片描述

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*>q;
        vector<double> result;
        if(!root)return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            vector<int> tmp;
            double sum = 0;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                sum += node->val;
                q.pop();
                if(i==k-1) result.push_back(sum/k);
                if(node->left)q.push(node->left);
                if(node->right)q.push(node->right);
            }
        }
        return result;
    }
};

429. N 叉树的层序遍历

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> q;
        vector<vector<int>>result;
        if(!root)return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            vector<int>tmp;
            for(int i =0;i<k;i++){
                Node* node = q.front();
                q.pop();
                tmp.push_back(node->val);
                for(auto c : node->children){
                    q.push(c);
                }
            }
            result.push_back(tmp);
        }
        return result;
    }
};

515.在每个树行中找最大值

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> q;
        vector<int> result;
        if(!root) return result;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            int maxV = INT_MIN;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                if(node -> val > maxV)maxV = node -> val;
                if(i == k-1)result.push_back(maxV);
                if(node -> left)q.push(node -> left);
                if(node -> right)q.push(node -> right);
            }
        }
        return result;
    }
};

116.填充每个节点的下一个右侧节点指针

在这里插入图片描述

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> q;
        if(!root) return root;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            Node* tmp = NULL;
            for(int i =0;i<k;i++){
                Node* node = q.front();
                q.pop();
                if(tmp != NULL)tmp -> next = node;
                tmp = node;
                if(node -> left)q.push(node -> left);
                if(node -> right)q.push(node -> right);
            }
        }
        return root;
    }
};

117.填充每个节点的下一个右侧节点指针II

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> q;
        if(!root) return root;
        q.push(root);
        while(!q.empty()){
            int k = q.size();
            Node* tmp = NULL;
            for(int i =0;i<k;i++){
                Node* node = q.front();
                q.pop();
                if(tmp != NULL)tmp -> next = node;
                tmp = node;
                if(node -> left)q.push(node -> left);
                if(node -> right)q.push(node -> right);
            }
        }
        return root;
    }
};

104.二叉树的最大深度

在这里插入图片描述

class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> q;
        if(!root) return 0;
        q.push(root);
        int count = 0;
        while(!q.empty()){
            int k = q.size();
            count++;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                if(node -> left)q.push(node -> left);
                if(node -> right)q.push(node -> right);
            }
        }
        return count;
    }
};

111.二叉树的最小深度

如果是叶子节点提前返回

class Solution {
public:
    int minDepth(TreeNode* root) {
        queue<TreeNode*> q;
        if(!root) return 0;
        q.push(root);
        int count = 0;
        while(!q.empty()){
            int k = q.size();
            count++;
            for(int i =0;i<k;i++){
                TreeNode* node = q.front();
                q.pop();
                if(!node -> left && !node -> right)return count;
                if(node -> left)q.push(node -> left);
                if(node -> right)q.push(node -> right);
            }
        }
        return count;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

掌机系统MuOS游戏名称中文乱码解决主题

最近买了安伯尼克的rg35xxh掌机来玩儿&#xff0c;然后刷了muos&#xff0c;系统很小巧&#xff0c;1g的运行内存&#xff0c;系统运行的时候只占用了不到100m&#xff0c;而且界面也很美观&#xff0c;就是有一个问题——中文名称会乱码&#xff0c;都变成了方框&#xff0c;从…

如何给IP地址开启https—IP证书

先IP地址申请的前提&#xff1a;80端口有打开&#xff0c;或者可以短暂的打开10分钟左右等验证完IP管理权再关掉。 一&#xff1a;访问JoySSL官网&#xff0c;注册账号并填写注册码230922&#xff0c;选择IP地址证书并下单加入购物车&#xff0c;下单之后就会跳转到证书申请界…

Linux--应用层协议HTTP协议(http服务器构建)

目录 1.HTTP 协议 2.认识 URL 3.urlencode 和 urldecode&#xff08;编码&#xff09; urlencode&#xff08;URL编码&#xff09; urldecode&#xff08;URL解码&#xff09; 4.HTTP 协议请求与响应格式 4.1HTTP 常见方法&#xff08;三种&#xff09; 5.HTTP 的状态码…

C++:命名空间与输入输出

目录 前言 一、命名空间 1.1 namespace的价值 1.2 namespace的定义 1.3 命名空间的使用 二、C输入&输出 前言 C是一种面向对象的计算机程序设计语言&#xff0c;‌它扩展了C语言的功能&#xff0c;‌并引入了面向对象编程的概念&#xff0c;‌如类、‌继承和多态等&a…

【笔记】从零开始做一个精灵龙女-画贴图阶段(下)

补充四点&#xff0c;第一&#xff0c;前期画体积用一号或十三号笔刷&#xff0c;压力60&#xff0c;硬度80&#xff0c;体积大一点 2号笔刷比较适合画过渡和软一点的东东 第二&#xff0c; 游戏里面角色原画海报都是发光很亮很透。但是在bp不能画那么亮&#xff0c;因为你进…

git强制推送代码教程

git强制推送代码教程 首先说明情况&#xff0c;我的代码remote了两个git库&#xff0c;现在想要推送到其中一个&#xff0c;但是版本不对&#xff0c;被拒绝&#xff0c;因此下面将进行强制推送 首先检查远程库都有哪些 git remote -v2. 检查当前的分支 git branch当前分支前…

Python 初学者入门:揭秘 Anaconda

初学者在学习 Python 时&#xff0c;经常看到的一个名字是 Anaconda。究竟什么是 Anaconda&#xff0c;为什么它如此受欢迎&#xff1f;在这篇文章中&#xff0c;我们将探讨 Anaconda &#xff0c;了解 Anaconda 的从安装到使用的。 Anaconda 是一个免费开源的 Python 和 R 编…

PCL 三线性插值

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 三线性插值是一种在三维空间中使用已知数据点进行插值的方法。它是在立方体内的插值方法,通过利用立方体的八个顶点的已知值来估算立方体内任意一点的值。三线性插值扩展了一维的线性插值和二维的双线性插值。其基…

数据结构入门——06树

1.树 树&#xff08;Tree&#xff09;非线性数据结构&#xff0c;它是n&#xff08;n≥0&#xff09;个节点的有限集合&#xff0c;它满足两个条件 &#xff1a; 有且仅有一个特定的称为根&#xff08;Root&#xff09;的节点&#xff1b; 其余的节点可以分为m&#xff08;m…

一文带你快速了解——keepalived高可用集群

一、高可用集群 1.1 集群类型 LB&#xff1a;Load Balance 负载均衡LVS/HAProxy/nginx&#xff08;http/upstream, stream/upstream&#xff09;HA&#xff1a;High Availability 高可用集群 数据库、RedisSPoF: Single Point of Failure&#xff0c;解决单点故障HPC&#xf…

Java_finalize

目录 finalize方法 案例演示 finalize方法 当垃圾回收器确定不存在对该对象的更多引用时&#xff0c;由对象的垃圾回收器调用此方法。 当对象被回收时&#xff0c;会自动调用&#xff0c;子类可以重写该方法&#xff0c;做一些释放资源的操作。 案例演示 可以使用快捷键进行…

一台电脑同时开多个微信

这几天闲没事&#xff0c; 就在网上查了一些相关的一台电脑同时开多个微信。经测试&#xff0c;确实可以做的&#xff0c;而且一点了不麻烦。经本人测试&#xff0c;把信息补全一些... 同时登录了两个微信&#xff0c;为什么只能两个微信&#xff0c;因为我只有两个微信。废话少…

leetcode412. Fizz Buzz,简单遍历

leetcode412. Fizz Buzz 给你一个整数 n &#xff0c;找出从 1 到 n 各个整数的 Fizz Buzz 表示&#xff0c;并用字符串数组 answer&#xff08;下标从 1 开始&#xff09;返回结果&#xff0c;其中&#xff1a; answer[i] “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。 answ…

0到1学习Google广告(2):掌握展示位置及排名规则丨出海笔记

大家好, 我是专注谷歌广告和谷歌SEO的谷哥哥哥&#xff0c;感谢出海笔记Alan邀请。今天我们来聊聊广告界的大拿——谷歌广告。在这个数字营销的黄金时代&#xff0c;无论是B2B、B2C还是品牌类客户&#xff0c;谷歌广告都是一个不容忽视的战场。那么&#xff0c;如何在这个战场上…

得物Flink内核探索实践

一、前言 随着大数据技术的飞速发展&#xff0c;实时处理能力变得越来越重要。在众多实时处理框架中&#xff0c;Apache Flink以其强大的流处理能力和丰富的功能集&#xff0c;受到了广泛关注和应用。在实时业务日益增长的趋势下&#xff0c;这促使我们深入探索Flink的内核&am…

程序员的第一法则:DRY —— 永远不要重复自己

1. 前言 在编程的世界里&#xff0c;有一条被广泛接受且极其重要的法则&#xff0c;它简明扼要&#xff0c;却道出了高效编程的核心&#xff1a;DRY&#xff0c;即 Don’t Repeat Yourself&#xff08;不要重复自己&#xff09;。这不仅仅是一句口号&#xff0c;而是每个程序员…

解锁微信公众号超强功能,让你的品牌火遍朋友圈!

微信公众号是微信官方提供的一种自媒体平台&#xff0c;允许个人和企业在微信上创建自己的公众号&#xff0c;并通过公众号发布文章、图片、视频等多种形式的内容。 微信公众号主要分为订阅号、服务号等类型。企业和个人可以使用公众号吸引关注者&#xff0c;与关注者进行互动…

计算机网络 DNS HTTP HTTPS,缓存

文章目录 输入URL之后的全过程URL URI DNS (Domain Name System)为什么分布式域名的层级关系解析过程递归查询和迭代查询 HTTP特性版本演变0.91.01.1问题优化 2兼容改变推送实现与HTTP1对比并发实现缺陷 3特点QUIC协议 缓存强制缓存协商缓存基于Last-Modified和If-Modified-Sin…

海外问卷调查的目的与动态IP的需求

海外问卷调查是一种重要的市场调研方式&#xff0c;被广泛应用于企业和组织对特定市场、产品或服务的深入了解。这种调研方法通过向目标市场的消费者发放问卷&#xff0c;收集他们对某一产品、服务或市场的看法和意见&#xff0c;从而帮助企业或组织更好地把握市场需求&#xf…