给定二叉树的前序遍历和中序遍历结果,请恢复出二叉树并打印出二叉树的右视图。
输入:
[1,2,4,5,3]
[4,2,5,1,3]
重建出的二叉树如下:
1
/ \
2 3
/ \
4 5
对应的右视图为 [1, 3, 5]
。
我们首先需要一个辅助函数来查找某个值在中序遍历中的位置,以便于重建树。
// 辅助函数:在数组中查找某个值的索引
int findIndex(int* inorder, int Start, int End, int val) {
for (int i = Start; i <= End; i++) {
if (val == inorder[i])
return i;
}
return -1;
}
根据前序遍历和中序遍历,递归重建二叉树。前序遍历给出了根节点,而中序遍历帮助我们确定左右子树的范围。
// 重建二叉树的函数
struct TreeNode* buildTree(int* preorder, int preorderStart, int preorderEnd,
int* inorder, int inorderStart, int inorderEnd) {
if (preorderStart > preorderEnd) {
return NULL; // 如果前序遍历的范围无效,返回NULL
}
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = preorder[preorderStart]; // 根节点值为前序遍历的第一个元素
int rootIndex = findIndex(inorder, inorderStart, inorderEnd, root->val); // 查找根节点在中序遍历中的位置
int leftTreeSize = rootIndex - inorderStart; // 左子树的大小
// 构建左子树
root->left = buildTree(preorder, preorderStart + 1,
preorderStart + leftTreeSize, inorder, inorderStart, rootIndex - 1);
// 构建右子树
root->right = buildTree(preorder, preorderStart + leftTreeSize + 1, preorderEnd,
inorder, rootIndex + 1, inorderEnd);
return root;
}
右视图是指从右侧看二叉树时,看到的所有节点。我们可以利用层次遍历(广度优先遍历,BFS)来实现。对于每一层,我们记录每一层的最后一个节点值。
// 输出二叉树的右视图
void rightsee(struct TreeNode* root, int** result, int* resultSize) {
if (root == NULL) {
*resultSize = 0;
return;
}
// 使用队列存储节点
struct TreeNode** queue = (struct TreeNode**)malloc(10000 * sizeof(struct TreeNode*));
int front = 0, rear = 0;
queue[rear++] = root;
while (front < rear) {
int levelSize = rear - front; // 当前层的节点数
for (int i = 0; i < levelSize; i++) {
struct TreeNode* node = queue[front++]; // 出队当前节点
if (i == levelSize - 1) { // 当前层的最后一个节点
(*result)[*resultSize] = node->val; // 记录最后一个节点的值
(*resultSize)++;
}
if (node->left) {
queue[rear++] = node->left; // 左子树入队
}
if (node->right) {
queue[rear++] = node->right; // 右子树入队
}
}
}
free(queue); // 释放队列
}
主函数调用重建二叉树函数,并获取右视图结果。
// 主函数:求二叉树的右视图
int* solve(int* preOrder, int preOrderLen, int* inOrder, int inOrderLen,
int* returnSize) {
struct TreeNode* tree = buildTree(preOrder, 0, preOrderLen - 1, inOrder, 0, inOrderLen - 1);
int* result = (int*)malloc(10000 * sizeof(int));
*returnSize = 0;
rightsee(tree, &result, returnSize); // 获取右视图
return result;
}
重建二叉树:
使用前序遍历的第一个节点作为根节点,通过中序遍历确定左子树和右子树的范围,然后递归构建左右子树。
输出右视图:
通过层次遍历,逐层记录每一层的最后一个节点,最终得到二叉树的右视图。
时间复杂度: O ( n ) O(n) O(n)
每个节点都会被访问一次,因此时间复杂度为 O ( n ) O(n) O(n)。
空间复杂度: O ( n ) O(n) O(n)
使用队列进行层次遍历,最坏情况下队列的大小为 O ( n ) O(n) O(n)。此外,递归栈的深度也是 O ( n ) O(n) O(n)。
通过前序遍历和中序遍历重建二叉树,再通过层次遍历获取右视图,是解决该问题的有效方法。