刷题 二叉树

二叉树的核心思想 - 递归 - 将问题分解为子问题

题型

  • 递归遍历
  • 迭代遍历
  • 层序遍历 bfs:队列
  • 各种递归题目:将问题分解为子问题
  • 二叉搜索树 - 中序遍历是递增序列 TreeNode* &prev 指针
  • 树形dp

面试经典 150 题 - 二叉树

104. 二叉树的最大深度

在这里插入图片描述

广度优先遍历

class Solution {
public:
    // 广度优先遍历
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        queue<TreeNode*> que;
        que.push(root);
        int result = 0;
        while (!que.empty()) {
            ++result;
            int num = que.size();
            while (num--) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return result;
    }
};

递归

最大深度 = 1 + max(左子树最大深度, 右子树最大深度)

class Solution {
public:
    // 递归:最大深度 = 1 + max(左子树最大深度, 右子树最大深度)
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        return 1 + max(maxDepth(root->left), maxDepth(root->right));
    }
};

100. 相同的树

在这里插入图片描述

递归

树相同 --> 根节点相同 + 左子树相同 + 右子树相同

class Solution {
public:
    // 递归
    // 树相同 --> 根节点相同 + 左子树相同 + 右子树相同
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (p == nullptr && q == nullptr) {
            return true;
        } else if (p == nullptr || q == nullptr) {
            return false;
        }
        if (p->val != q->val) {
            return false;
        }
        if (isSameTree(p->left, q->left) == false) {
            return false;
        }
        if (isSameTree(p->right, q->right) == false) {
            return false;
        }
        return true;
    }
};

226. 翻转二叉树

在这里插入图片描述

递归

class Solution {
public:
    // 翻转二叉树 --> 
    // 根节点的左子树 = 将右子树进行反转
    // 根节点的右子树 = 将左子树进行反转
    TreeNode *invertTree(TreeNode *root) {
        if (root == nullptr) return nullptr;
        auto left = invertTree(root->left); // 翻转左子树
        auto right = invertTree(root->right); // 翻转右子树
        root->left = right; // 交换左右儿子
        root->right = left;
        return root;
    }
};

⭐️⭐️112. 路径总和

在这里插入图片描述

回溯

class Solution {
public:
    // 回溯
    bool backtracking(TreeNode* root, int path_sum, int targetSum) { 
        if (root == nullptr) return false;
        if (root->right == nullptr && root->left == nullptr) {  // 到达叶子节点,终止回溯
            return (path_sum + root->val == targetSum);
        }
        return (backtracking(root->left, path_sum + root->val, targetSum) || \
                backtracking(root->right, path_sum + root->val, targetSum));
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        return backtracking(root, 0, targetSum);
    }
};

⭐️⭐️迭代

class Solution {
public:
    // 递归: 树 存在和为 targetSum
    // 也即左子树存在和为 targetSum - root->val 或者 右子树存在和为 targetSum - root->val
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == nullptr) return false;
        if (root->left == nullptr && root->right == nullptr) {
            return (targetSum == root->val); 
        } 
        return (hasPathSum(root->left, targetSum - root->val) || \
                hasPathSum(root->right, targetSum - root->val));
    }
};

层序遍历

比较简单,不做讨论

面试经典 150 题 - 二叉树层次遍历

199. 二叉树的右视图

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

637. 二叉树的层平均值

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        if (root == nullptr) return vector<double>{};
        queue<TreeNode*> que;
        que.push(root);
        vector<double> result;
        while (!que.empty()) {
            size_t n = que.size();
            double sum = 0.0;
            for (size_t i = 0; i < n; ++i) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
                sum += cur->val;
            }
            result.push_back(sum / n);
        }
        return result;
    }
};

[102. 二叉树的层序遍历

](https://leetcode.cn/problems/binary-tree-level-order-traversal/?envType=study-plan-v2&envId=top-interview-150)

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if (root == nullptr) return vector<vector<int>>{};
        queue<TreeNode*> que;
        que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            size_t n = que.size();
            vector<int> layer(n, 0);
            for (size_t i = 0; i < n; ++i) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
                layer[i] = cur->val;
            }
            result.push_back(layer);
        }
        return result;
    }
};

103. 二叉树的锯齿形层序遍历 - 写入的时候改一下索引即可

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if (root == nullptr) return vector<vector<int>>{};
        queue<TreeNode*> que;
        que.push(root);
        vector<vector<int>> result;
        bool to_right = false;
        while (!que.empty()) {
            to_right = !to_right;
            size_t n = que.size();
            vector<int> layer(n, 0);
            for (size_t i = 0; i < n; ++i) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
                if (to_right) {
                    layer[i] = cur->val;
                } else {
                    layer[n - 1 - i] = cur->val;
                }
            }
            result.push_back(layer);
        }
        return result;
    }
};

面试经典 150 题 - 二叉搜索树 - ⭐️TreeNode*& prev⭐️ - 中序遍历有序

98. 验证二叉搜索树

class Solution {
public:
    bool traversal(TreeNode* root, TreeNode*& prev) {
        if (root == nullptr) return true;
        if (!traversal(root->left, prev)) return false;
        if (prev != nullptr && prev->val >= root->val) return false;
        prev = root;
        return traversal(root->right, prev);
    }

    bool isValidBST(TreeNode* root) {
        TreeNode* prev = nullptr;
        return traversal(root, prev);
    }
};

530. 二叉搜索树的最小绝对差

在这里插入图片描述

使用数组暂存

class Solution {
public:
    // 二叉搜索树的特征:左子树 < 根节点 < 右子树
    // 中序遍历即可获得最小差值
    void traversal(TreeNode* root, vector<int>& vals, int& min_diff) {
        if (root == nullptr) return;
        traversal(root->left, vals, min_diff);
        if (!vals.empty()) min_diff = min(min_diff, root->val - vals.back()); 
        vals.push_back(root->val);
        traversal(root->right, vals, min_diff);
    }
    int getMinimumDifference(TreeNode* root) {
        vector<int> vals;
        int min_diff = INT_MAX;
        traversal(root, vals, min_diff);
        return min_diff;
    }
};

⭐️优化 - 使用一个 prev_val 即可

class Solution {
public:
    // 二叉搜索树的特征:左子树 < 根节点 < 右子树
    // 中序遍历即可获得最小差值
    // 如果不想使用数组暂存的话就需要存储一个 prev 指针
    void traversal(TreeNode* root, TreeNode*& prev, int& min_diff) {
        if (root == nullptr) return;
        traversal(root->left, prev, min_diff);
        if (prev != nullptr) min_diff = min(min_diff, root->val - prev->val); 
        prev = root;
        traversal(root->right, prev, min_diff);
    }
    int getMinimumDifference(TreeNode* root) {
        int min_diff = INT_MAX;
        TreeNode* prev = nullptr;
        traversal(root, prev, min_diff);
        return min_diff;
    }
};

230. 二叉搜索树中第 K 小的元素 - 想象用数组存储元素 - 实际只使用索引即可 - 注意终止条件

class Solution {
public:
    void traversal(TreeNode* root, int& val, int& count, int k) {
        if (root == nullptr || count >= k) return;  // 递归终止条件
        traversal(root->left, val, count, k);
        ++count;    // 如果用数组存储元素,想象这里是数组的第 count 个数字(从0开始)
        if (count == k) {
            val = root->val;
            return;
        }
        traversal(root->right, val, count, k);
    }
    int kthSmallest(TreeNode* root, int k) {
        int val, count = 0;
        traversal(root, val, count, k);
        return val;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

边缘人工智能(Edge Intelligence)

边缘人工智能&#xff08;Edge AI&#xff09;是指在边缘设备上直接运行人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;算法的技术。机器学习是一个广泛的领域&#xff0c;近年来取得了巨大的进步。它所基于的原则是&#xff0c;计算机可以通过从数据…

gaussdb hccdp认证模拟题(判断)

1.在事务ACID特性中&#xff0c;原子性指的是事务必须始终保持系统处于一致的状态。(1 分) 错。 2.某IT公司在开发软件时&#xff0c;需要使用GaussDB数据库&#xff0c;因此需要实现软件和数据的链接&#xff0c;而DBeaver是一个通用的数据库管理工具和 SQL 客户端&#xff…

T536 工业级设备处理器:为智能硬件与工业应用打造的高性能解决方案

T536 工业级设备处理器&#xff1a;为智能硬件与工业应用打造的高性能解决方案 引言 在当今快速发展的科技时代&#xff0c;工业自动化和智能硬件领域对处理器的需求日益增长。为了满足这一需求&#xff0c;Allwinner Technology推出了T536系列处理器&#xff0c;这是一款专为…

大数据行业应用实训室建设方案

摘要&#xff1a; 本文旨在探讨唯众针对当前大数据行业的人才需求&#xff0c;提出的《大数据行业应用实训室建设方案》。该方案旨在构建一个集理论教学、实践操作、技术创新与行业应用于一体的综合实训平台&#xff0c;以培养具备实战能力的大数据专业人才。 一、大数据课程体…

无人机之飞行算法篇

无人机的飞行算法是一个复杂而精细的系统&#xff0c;它涵盖了多个关键技术和算法&#xff0c;以确保无人机能够稳定、准确地执行飞行任务。 一、位置估计 无人机在空中飞行过程中需要实时获取其位置信息&#xff0c;以便进行路径规划和控制。这通常通过以下传感器实现&#…

MFC多媒体定时器实例(源码下载)

用MFC多媒体定时器做一个每1秒钟加一次的计时器&#xff0c;点开始计时按钮开始计时&#xff0c;点关闭计时按钮关闭计时。 1、在库文件Med_timeDlg.h文件中添加代码 class CMed_timeDlg : public CDialog { // Construction public:CMed_timeDlg(CWnd* pParent NULL); // st…

No.14 笔记 | XSS漏洞:原理、类型与防御策略

一、HTML和JavaScript基础 1. HTML基础 HTML概述&#xff1a;超文本标记语言&#xff0c;用于实现页面跳转和显示数据。结构标准&#xff1a;包括<!doctype html>声明文档类型&#xff0c;<html>根标签&#xff0c;<head>头部标签和<body>主体标签等。…

Docsify搭建个人博客

前提&#xff1a;电脑安装了Node.js 安装到本地 CMD命令下输入node -v查看是否已经安装了Node.js 安装docsify-cli工具&#xff1a;npm i docsify-cli -g 使用git下载docsify-Plus项目&#xff0c;Gitee地址&#xff1a;https://gitee.com/librarycodes/docsify-plus cd…

Linux安装RabbitMQ安装

1. RabbitMQ介绍 1.1 RabbitMQ关键特性 异步消息传递&#xff1a;允许应用程序在不直接进行网络调用的情况下交换消息。 可靠性&#xff1a;支持消息持久化&#xff0c;确保消息不会在系统故障时丢失。 灵活的路由&#xff1a;支持多种路由选项&#xff0c;包括直接、主题、…

建筑物能耗模拟软件EnergyPlus下载安装及使用

建筑物能耗模拟软件EnergyPlus下载安装及使用 EnergyPlus概述EnergyPlus下载及安装EnergyPlus安装 EnergyPlus使用参考 建筑物能耗模拟软件是一种在建筑设计阶段使用的工具&#xff0c;能够透过电脑模拟预测未来建筑物的能耗情况&#xff0c;达成建筑性能模拟。这有助于评估不同…

C# HttpClient请求URL重定向后丢失Authorization认证头信息 .Net Core Web Api

问题: 使用.Net 入库Doris请求FE端口后,FE响应重定向到其他BE节点出现的认证失败问题。 搜查官方文档后发现&#xff1a; HttpWebRequest.AllowAutoRedirect Property (System.Net) | Microsoft Learn 微软提供的http类库HttpClient &#xff08;HttpWebRequest\WebClient已不…

python的内存管理机制

python的内存管理机制主要分为三个部分&#xff1a;引用计数、垃圾回收和内存池机制。 引用计数机制&#xff1a; python通过维护每个对象的引用计数来跟踪内存中的对象。当对象被创建时就会有一个引用计数&#xff0c;当对象不再被使用时&#xff0c;引用计数为0&#xff0c…

5.错误处理在存储过程中的重要性(5/10)

错误处理在存储过程中的重要性 引言 在数据库编程中&#xff0c;存储过程是一种重要的组件&#xff0c;它允许用户将一系列SQL语句封装成一个单元&#xff0c;以便重用和简化数据库操作。然而&#xff0c;像任何编程任务一样&#xff0c;存储过程中的代码可能会遇到错误或异常…

攻防世界---->[简单] 初识RSA

做题笔记。 下载 是一个.py的文件。 用 Notepad打开瞅瞅。 分析&#xff1a; L (p-1)*(q-1) dgmpy2.invert(e,L) 求逆元快速算出来&#xff1a;invert(e,φ(N)) 求出d值。 n p*q pq p*(q-1) qp q*(p-1) L 【q*(p-1) * p*(q-1)】 // p*q >>> (p-1)*(…

通信工程学习:什么是OSPF开放式最短路径优先

OSPF&#xff1a;开放式最短路径优先 OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09;是一种内部网关协议&#xff08;IGP&#xff09;&#xff0c;被广泛应用于计算机网络中&#xff0c;特别是在构建大型和复杂的网络时。以下是对OSPF的…

Pikachu-url重定向-不安全的url跳转

不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话就可能发生"跳错对象"的问题。 url跳转比较直接的危害是: …

Dev-C++ 安装与使用(dev c++官网)(已解决)

1.Dev-C的安装 ①打开Dev-C的官网(https://sourceforge.net/projects/orwelldevcpp/ )&#xff1b;点击Download(下载)&#xff0c;等待5秒后开始下载。 ②点开下载好的EXE文件&#xff0c;等待加载完成(如图)。 右键&#xff0c;以管理员身份 运行安装包。 选择English(英语),…

JVS·智能BI数据可视化图表:普通列表与分组列表配置全解析

使用场景 在可视化配置中&#xff0c;很多场景中需要图形和详细信息的融合展示&#xff0c;那么在图表中可以新增普通列表与分组列表的配置。如下图所示&#xff1a; 配置说明 1、新增组件&#xff1a;配置入口如下图所示&#xff0c;新增组件时&#xff0c;选择普通列表与分…

浅谈司库决策分析体系建设

一 、前言&#xff1a;司库管理体系建设 2022年国务院国资委印发《关于推动中央企业加快司库体系建设进一步加强资金管理的意见》&#xff0c;指出司库管理体系是企业集团依托财务公司、资金中心等管理平台&#xff0c;运用现代网络信息技术&#xff0c;以资金集中和信息集中为…

【iOS】计算器仿写

计算器 前言四则运算View层Masonry布局 非法输入的逻辑 前言 前两周进行了计算器的仿写&#xff0c;运用了刚学习的Masonry布局以及MVC框架&#xff0c;同时学习了简单的四则运算&#xff0c;今天撰写博客对计算器的仿写进行一个总结&#xff0c;整理归纳期间遇到的问题和收获…