想象你站在一棵二叉树的右侧,从上往下看,每一层你只能看到最右边的那个节点。这就是题目要求我们实现的"右视图"。例如对于二叉树:
code复制 1
/ \
2 3
\ \
5 4
它的右视图应该是 [1, 3, 4]。
最直观的解法是使用广度优先搜索(BFS)进行层序遍历。在遍历每一层时,我们只需要记录该层的最后一个节点即可。这是因为:
让我们仔细分析给出的C++实现代码:
cpp复制class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<int> result;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == (size - 1)) result.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
queue<TreeNode*>来存储待处理的节点vector<int>用于存储右视图结果size记录当前层的节点数,确保我们只处理当前层size = que.size():这个操作非常重要,它记录了当前层的节点数量,让我们能够区分不同层的节点i == (size - 1):这个条件判断当前节点是否是当前层的最后一个节点该算法需要访问二叉树中的每个节点一次,因此时间复杂度为O(n),其中n是二叉树的节点数。
空间复杂度主要取决于队列中存储的节点数量。在最坏情况下(完全二叉树),队列中最多会存储约n/2个节点(最后一层的节点数),因此空间复杂度也是O(n)。
在实际编码中,我们需要考虑以下几种特殊情况:
给出的代码已经正确处理了这些边界情况。
除了BFS,我们还可以使用DFS来解决这个问题:
cpp复制class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> result;
dfs(root, 0, result);
return result;
}
void dfs(TreeNode* node, int depth, vector<int>& result) {
if (!node) return;
if (depth == result.size()) {
result.push_back(node->val);
}
dfs(node->right, depth + 1, result);
dfs(node->left, depth + 1, result);
}
};
这种解法先访问右子树,只有当当前深度还没有记录节点时(即depth == result.size()),才记录当前节点值。
BFS优势:
DFS优势:
二叉树的右视图问题在实际中有多种应用:
如果我们想实现二叉树的左视图,只需要稍作修改:
cpp复制if (i == 0) result.push_back(node->val); // 记录每层第一个节点
俯视图(top view)的实现会更复杂一些,需要考虑节点的水平距离,通常需要使用哈希表来记录每个水平距离的第一个节点。
在实际应用中,我们可能需要同时获取左视图、右视图、俯视图等多种视角的信息。这时可以考虑设计一个更通用的遍历框架,一次收集所有需要的信息。