当前位置: 首页 > article >正文

LeetCodehot 力扣热题100 二叉树的右视图

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> ans;  // 用于存储从右侧看每一层的节点值
        int layer = 1;  // 从根节点开始,层级是1
        rightSideViewfunction(root, layer, ans);  // 调用辅助函数进行递归遍历
        return ans;  // 返回结果
    }
    
    void rightSideViewfunction(TreeNode *root, int layer, vector<int> &ans) {
        if (root != nullptr) {  // 如果当前节点为空,返回
            // 如果当前层级还没有记录节点值,则将当前节点的值加入答案
            if (layer > ans.size()) 
                ans.push_back(root->val);  // 把当前节点值加入答案

            // 递归遍历右子树,先遍历右子树保证右边的节点先被访问到
            rightSideViewfunction(root->right, layer + 1, ans);
            
            // 递归遍历左子树
            rightSideViewfunction(root->left, layer + 1, ans);
        }
    }
};

下面是对你提供的 C++ 代码的详细解释、注释和思路解析。

题目思路

这个代码的目标是给定一个二叉树,返回从右侧看每一层的节点值。也就是说,我们需要按层级遍历树,记录每一层最右边的节点。

思路解析

1. 层级遍历:我们需要遍历每一层的节点。由于问题要求“从右侧看”,我们可以先遍历右子树,然后是左子树,这样就能保证每次遍历到的第一个节点是右侧的节点。

2. 递归遍历:采用递归深度优先遍历(DFS)来解决。每次递归中,判断当前的层级(layer)是否已经有节点被记录。如果没有,则把当前节点值加入答案。

3. 记录答案:答案是一个按层级从上到下、从右到左的节点值列表。

好的,下面我会更详细地解释这段代码的运行步骤,逐步模拟递归过程,并结合一个例子来说明每个步骤是如何执行的。

假设我们有如下的二叉树:

        1

       / \

      2   3

       \   \

        5   4

我们从右侧视角来看每一层的节点,最终输出 [1, 3, 4],即从右侧看每一层的最右节点。

递归调用的详细步骤

1. 初始调用

• rightSideView(root) 被调用时,root 是树的根节点,值为 1。接着它调用了辅助函数 rightSideViewfunction(root, 1, ans),layer 初始化为 1,ans 是一个空的 vector<int>。

2. 第 1 层

• 当前节点:root = 1,layer = 1。

• 进入 rightSideViewfunction 函数:

• root 不是 nullptr,继续判断层级。

• 当前层级 1 > ans.size() = 0,说明第 1 层的节点值还没有被记录,所以把 1 加入 ans。

• ans = [1]。

• 递归调用右子树:rightSideViewfunction(root->right, 2, ans),root->right 是节点 3,layer = 2。

3. 第 2 层(右子树)

• 当前节点:root = 3,layer = 2。

• 进入 rightSideViewfunction 函数:

• root 不是 nullptr,继续判断层级。

• 当前层级 2 > ans.size() = 1,说明第 2 层的节点值还没有被记录,所以把 3 加入 ans。

• ans = [1, 3]。

• 递归调用右子树:rightSideViewfunction(root->right, 3, ans),root->right 是节点 4,layer = 3。

4. 第 3 层(右子树)

• 当前节点:root = 4,layer = 3。

• 进入 rightSideViewfunction 函数:

• root 不是 nullptr,继续判断层级。

• 当前层级 3 > ans.size() = 2,说明第 3 层的节点值还没有被记录,所以把 4 加入 ans。

• ans = [1, 3, 4]。

• 由于节点 4 没有左右子树,递归返回到上一层。

5. 回到第 2 层(继续遍历左子树)

• 当前节点:root = 3,layer = 2。

• 继续递归遍历左子树:rightSideViewfunction(root->left, 3, ans),root->left 是 nullptr,直接返回。

6. 回到第 1 层(继续遍历左子树)

• 当前节点:root = 1,layer = 1。

• 继续递归遍历左子树:rightSideViewfunction(root->left, 2, ans),root->left 是节点 2,layer = 2。

7. 第 2 层(左子树)

• 当前节点:root = 2,layer = 2。

• 进入 rightSideViewfunction 函数:

• root 不是 nullptr,继续判断层级。

• 当前层级 2 ≤ ans.size() = 3,说明第 2 层的节点值已经记录了,所以不再加入 ans。

• ans = [1, 3, 4],没有变化。

• 递归调用右子树:rightSideViewfunction(root->right, 3, ans),root->right 是节点 5,layer = 3。

8. 第 3 层(右子树)

• 当前节点:root = 5,layer = 3。

• 进入 rightSideViewfunction 函数:

• root 不是 nullptr,继续判断层级。

• 当前层级 3 ≤ ans.size() = 3,说明第 3 层的节点值已经记录了,所以不再加入 ans。

• ans = [1, 3, 4],没有变化。

• 由于节点 5 没有左右子树,递归返回到上一层。

9. 回到第 2 层(继续遍历左子树)

• 当前节点:root = 2,layer = 2。

• 继续递归遍历左子树:rightSideViewfunction(root->left, 3, ans),root->left 是 nullptr,直接返回。

10. 结束

• 所有节点都已经被遍历过,递归完成。

最终结果

经过以上递归步骤后,最终的 ans 数组是 [1, 3, 4],即从右侧看每一层的最右边的节点值。

总结

通过这段代码的递归过程,我们能够实现从右侧查看每一层的最右节点的功能。递归的关键在于:

• 使用 layer 来表示当前层级。

• 从右子树先行遍历,这样保证了每次访问的第一个节点是右侧的节点。

• 使用 ans.size() 判断每一层是否已经有节点值记录,从而确保每层只有最右边的节点值被记录。

时间复杂度:O(n),其中 n 是树的节点数。每个节点都被访问一次。

空间复杂度:O(h),其中 h 是树的高度,用于递归栈的空间。如果树是平衡的,空间复杂度为 O(log n),如果是单链表形状的树,空间复杂度为 O(n)。


http://www.kler.cn/a/548543.html

相关文章:

  • 如何正确安装Stable Diffusion Web UI以及对应的xFormers
  • mysql的rpm包安装
  • 【C++指南】不允许你不了解C++命名空间
  • Spring Boot 定时任务:轻松实现任务自动化
  • SQL-leetcode—1581. 进店却未进行过交易的顾客
  • EtherNetIP转ModbusTCP网关,给风电注入“超级赛亚人”能量
  • SQL数据清理:去除字段值中的多余符号(Demo例子)
  • 【NLP 24、模型训练方式】
  • 负载均衡集群——LVS-DR配置
  • PowerBI 矩阵 列标题分组显示(两行列标题)
  • Golang 的字符编码与 regexp
  • 《Grafana进阶教程-使用百度地图》
  • 数据库设计流程范式
  • js 使用缓存判断在规定时间内显示一次弹框
  • wx061基于ssm+vue+uniapp的疫情期间学生请假与销假系统小程序
  • Maven 中的 `<dependencyManagement>` 标签及其高级用法
  • 【计算机网络】传输层数据段格式
  • Docker Remote API未授权访问漏洞复现
  • 国产编辑器EverEdit - 二进制模式下观察Window/Linux/MacOs换行符差异
  • 两个实用且热门的 Python 爬虫案例,结合动态/静态网页抓取和反爬策略,附带详细代码和实现说明