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) | 最优解 |
现在用的是 最优解
八、这题的本质
把左子树插到右边 + 接回原右子树
九、一句话总结
找到左子树最右节点,把右子树接过去,再把左子树移到右边