199.二叉树的右视图是LeetCode上一道经典的二叉树遍历问题,题目要求我们返回从右侧观察二叉树时能看到的节点值序列。这个问题看似简单,但实际考察了对二叉树层次遍历的深入理解和灵活应用能力。
给定一个二叉树的根节点root,想象你站在它的右侧,按照从顶部到底部的顺序,返回你能看到的节点值。例如对于以下二叉树:
code复制 1
/ \
2 3
\ \
5 4
从右侧观察,我们能看到节点1、3、4,因此正确的输出应该是[1,3,4]。
这个问题的关键在于理解"右视图"的定义。从右侧观察时,每一层最右边的节点会遮挡它左边的所有节点。因此,我们需要找到二叉树每一层的最右侧节点。
最直观的解法是使用广度优先搜索进行层次遍历,记录每一层的最后一个节点。这种方法时间复杂度为O(n),空间复杂度为O(n),其中n是二叉树的节点数。
java复制public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int levelSize = queue.size();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
if (i == levelSize - 1) {
result.add(node.val);
}
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return result;
}
另一种思路是使用深度优先搜索,优先访问右子树。我们维护一个结果列表,当第一次到达某个深度时,将该节点加入结果列表。
java复制public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<>();
dfs(root, 0, result);
return result;
}
private void dfs(TreeNode node, int depth, List<Integer> result) {
if (node == null) return;
if (depth == result.size()) {
result.add(node.val);
}
dfs(node.right, depth + 1, result);
dfs(node.left, depth + 1, result);
}
两种方法都需要访问所有节点一次,因此时间复杂度都是O(n)。
BFS的空间复杂度取决于队列的最大长度,最坏情况下是O(n)。DFS的空间复杂度取决于递归栈的深度,最坏情况下也是O(n)。
只需修改BFS中保存第一个节点,或DFS中优先访问左子树即可实现左视图。
可以一次遍历同时记录每层的第一个和最后一个节点,减少遍历次数。
使用栈替代递归,避免递归带来的栈溢出风险。
java复制public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) return result;
Stack<TreeNode> nodeStack = new Stack<>();
Stack<Integer> depthStack = new Stack<>();
nodeStack.push(root);
depthStack.push(0);
while (!nodeStack.isEmpty()) {
TreeNode node = nodeStack.pop();
int depth = depthStack.pop();
if (depth == result.size()) {
result.add(node.val);
}
if (node.left != null) {
nodeStack.push(node.left);
depthStack.push(depth + 1);
}
if (node.right != null) {
nodeStack.push(node.right);
depthStack.push(depth + 1);
}
}
return result;
}
二叉树右视图问题虽然简单,但其思想可以应用于:
掌握二叉树右视图后,可以尝试解决以下相关问题:
虽然算法思想相同,但在不同语言中实现细节有所不同:
在实际项目中,类似的算法可以用于:
为了更好地理解算法执行过程,可以:
为二叉树右视图算法编写测试时应该:
对于大规模二叉树,可以:
保持代码可维护性的建议:
在团队项目中实现此类算法时:
二叉树右视图问题中体现的算法思想可以应用于: