【leetcode hot 100】二叉树二叉树

1.

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
       vector<int>result;
       if(!root) return result;
       queue<TreeNode*>q;
       q.push(root);
       while(!q.empty())
       {
            int treesize=q.size();
            for(int i=0;i<treesize;i++)
            {
                TreeNode* node=q.front();
                q.pop();
                if(i==treesize-1)
                {
                    result.push_back(node->val);
                }
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            } 
       }
       return result;
    }
};

这个题呢就是要求出每一层树的最右边的那个节点的值,之前做过一个题,就是要求逐层遍历,每一层每一层的遍历,这个题可以借鉴那个思路,是这样的,定义队列,把每一层的值加入,用for循环遍历每一层,遍历这一层的时候顺变删除这一层的值,删除完之后加入这个节点的子节点,这样子就刚好可以实现遍历完这一层之后队列里全是下一层的值,然后只需要把每一层最后的那个值加入result数组,最后输出数组就行了;

二叉树右视图(Right Side View):层序遍历一眼看穿

这道题本质不难,但非常经典,是**层序遍历(BFS)**的典型应用。


一、题目本质

从右侧看二叉树,返回能看到的节点

换句话说:

每一层的最后一个节点


二、核心思路

使用 层序遍历(BFS)

关键点只有一个:

记录每一层的最后一个节点


三、整体框架

复制代码
vector<int> rightSideView(TreeNode* root)

步骤:

  • 判空

  • 使用队列进行层序遍历

  • 每层取最后一个节点


四、代码拆解

1. 判空

复制代码
if (!root) return result;

2. 初始化队列

复制代码
queue<TreeNode*> q;
q.push(root);

BFS 标准操作


3. 按层遍历

复制代码
int levelSize = q.size();

记录当前层节点数量


4. 遍历当前层

复制代码
for (int i = 0; i < levelSize; i++)

一层一层处理


5. 核心逻辑(重点)

复制代码
if (i == levelSize - 1) {
    result.push_back(node->val);
}

当前层最后一个节点 = 右视图节点


6. 子节点入队

复制代码
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);

注意这里:

  • 先左后右没问题

  • 因为我们取的是"最后一个"


五、举个例子

复制代码
        1
       / \
      2   3
       \   \
        5   4

层序遍历:

复制代码
第1层:1        → 取 1
第2层:2 3      → 取 3
第3层:5 4      → 取 4

结果:

复制代码
[1, 3, 4]

六、另一种写法

DFS(优先右子树)

思路:

  • 先访问右边

  • 每层第一次访问就是答案

cpp 复制代码
void dfs(TreeNode* root, int depth, vector<int>& res) {
    if (!root) return;
    
    if (depth == res.size()) {
        res.push_back(root->val);
    }
    
    dfs(root->right, depth + 1, res);
    dfs(root->left, depth + 1, res);
}

七、时间复杂度

时间复杂度:

O(n)

空间复杂度:

O(n)

2.

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        TreeNode* curr = root;
        
        while (curr) {
            // 如果左子树存在
            if (curr->left) {
                // 找到左子树的最右节点
                TreeNode* pre = curr->left;
                while (pre->right) {
                    pre = pre->right;
                }
                
                // 将右子树接到最右节点的右边
                pre->right = curr->right;
                
                // 将左子树移到右边
                curr->right = curr->left;
                curr->left = nullptr;
            }
            
            // 继续处理下一个节点
            curr = curr->right;
        }
    }
};

这个题是这样的,他要按照链表那个样子排序,其实这个和前序遍历顺序是一样的,前序遍历是根左右这样的顺序进行的,他不是会不断递归到最左边的孩子嘛,到最左边的孩子之后再回溯根节点再到根的右边,那么咱们只需要利用这一点,把右子树的节点依次插在左子树最右边的右边,不断这样子来,走完一个节点就将左子树清空,右子树变成那个新形成的子树节点;然后对下一个节点继续这样子;

二叉树展开为链表(Flatten Binary Tree)详解:原地修改的经典套路

这道题是面试高频题,核心难点在于:

如何在"原地"把二叉树改成链表

你这份代码已经是最优解(O(1)空间),而且思路非常高级,我们来彻底讲透。


一、题目本质

把一棵二叉树展开成链表:

要求:

  • 前序遍历顺序

  • 使用 右指针连接

  • 左指针全部置空


二、目标结构

例如:

复制代码
    1
   / \
  2   5
 / \   \
3   4   6

变成:

复制代码
1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

本质就是:

前序遍历 + 指针重连


三、核心思路(重点)

你用的是:

类似 Morris 遍历的思想(空间 O(1))


四、代码拆解

1. 从根开始

复制代码
TreeNode* node = root;

2. 遍历整棵树

复制代码
while (node)

一直沿着右边走


3. 关键逻辑(精华)

复制代码
if (node->left)

如果当前节点有左子树,就要处理


4. 找前驱节点(关键一步)

复制代码
TreeNode* pre = node->left;
while (pre->right) {
    pre = pre->right;
}

找左子树中最右边的节点(前驱)


5. 重连结构(核心)

这三步非常关键:


第一步:

左子树的最右节点 → 接上原来的右子树

第二步:

当前节点右指针 → 指向左子树

第三步:

左子树置空


6. 向右继续

复制代码
node = node->right;

因为已经变成链表结构了


五、执行过程(必须理解)

拿这个例子:

复制代码
    1
   / \
  2   5

处理过程:

第一步(node=1)

  • 找到左子树最右:2

  • 2.right → 5

  • 1.right → 2

  • 1.left → null

变成:

复制代码
1
 \
  2
   \
    5

然后继续处理 2、5......


六、时间和空间复杂度

时间复杂度:

O(n)

空间复杂度:

O(1)(没有用递归 / 栈)


七、为什么这个方法很高级

对比三种解法:

方法 空间复杂度 说明
递归 O(h) 简单但用栈
栈模拟 O(n) 容易写
当前方法 O(1) 最优解

现在用的是 最优解


八、这题的本质

把左子树插到右边 + 接回原右子树


九、一句话总结

找到左子树最右节点,把右子树接过去,再把左子树移到右边

相关推荐
一直都在5722 小时前
B树和B+树详解
数据结构·b树
XiYang-DING2 小时前
【LeetCode】203. 移除链表元素(Remove Linked List Elements)
算法·leetcode·链表
墨神谕2 小时前
希尔排序详解
数据结构·算法·排序算法
胡楚昊2 小时前
Polar PWN (4)
linux·运维·算法
圣保罗的大教堂2 小时前
leetcode 2751. 机器人碰撞 困难
leetcode
今儿敲了吗2 小时前
51| 数独
算法·深度优先·图论
半瓶榴莲奶^_^2 小时前
优先级队列(堆)
java·数据结构·算法
小樱花的樱花2 小时前
C++引用:高效编程的技巧
开发语言·数据结构·c++·算法
Yupureki2 小时前
《算法竞赛从入门到国奖》算法基础:动态规划-最长子序列
c语言·c++·算法·动态规划