每日一题——输出二叉树的右视图

输出二叉树的右视图

    • 题目描述
      • 示例
    • 数据范围
    • 代码实现
      • 辅助函数
      • 重建二叉树
      • 输出二叉树的右视图
      • 主函数
    • 总结
      • 思路
      • 时间与空间复杂度
      • 结论

题目描述

给定二叉树的前序遍历和中序遍历结果,请恢复出二叉树并打印出二叉树的右视图。

示例

输入:

  • 前序遍历:[1,2,4,5,3]
  • 中序遍历:[4,2,5,1,3]

重建出的二叉树如下:

       1
     /   \
    2     3
   / \
  4   5

对应的右视图为 [1, 3, 5]

数据范围

  • 0 ≤ n ≤ 10000 0 \leq n \leq 10000 0n10000
  • 需要满足空间复杂度 O ( n ) O(n) O(n),时间复杂度 O ( n ) O(n) O(n)

代码实现

辅助函数

我们首先需要一个辅助函数来查找某个值在中序遍历中的位置,以便于重建树。

// 辅助函数:在数组中查找某个值的索引
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;
}

总结

思路

  1. 重建二叉树:
    使用前序遍历的第一个节点作为根节点,通过中序遍历确定左子树和右子树的范围,然后递归构建左右子树。

  2. 输出右视图:
    通过层次遍历,逐层记录每一层的最后一个节点,最终得到二叉树的右视图。

时间与空间复杂度

  • 时间复杂度: 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)

结论

通过前序遍历和中序遍历重建二叉树,再通过层次遍历获取右视图,是解决该问题的有效方法。

你可能感兴趣的:(面经,算法题,C语言,算法,数据结构,leetcode,c语言,二叉树)