二叉树的广度优先遍历 - 华为OD统一考试(D卷)

OD统一考试(D卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。

现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请输出层次遍历的结果。

输入描述

输入为两个字符串,分别是二叉树的后续遍历和中序遍历结果。

输出描述

输出二叉树的层次遍历结果。

示例1

输入:
CBEFDA CBAEDF

输出:
ABDCEF

说明:
二叉树为:
    A
   / \
  B   D
 /   / \
C   E   F

题解

  • 题目类型: 该题目是关于树的构建和遍历的问题。
  • 解题思路:
    • 首先需要根据给定的后序遍历和中序遍历构建二叉树。
    • 构建二叉树的过程可以通过递归实现。在递归中,根据后序遍历的最后一个节点确定根节点,在中序遍历中找到对应的根节点位置,从而分隔左右子树。
    • 构建好二叉树后,再进行层次遍历。层次遍历可以利用队列进行,从根节点开始,将每一层的节点依次加入队列,并输出值,直至队列为空。
  • 代码描述:
    • Java代码中,通过递归实现了树的构建,然后利用队列进行层次遍历。
    • Python代码和C++代码实现了同样的功能,Python代码利用了列表模拟队列,而C++代码使用了STL中的queue。
  • 时间复杂度:
    • 树的构建时间复杂度为O(N),其中N为节点数。
    • 层次遍历时间复杂度为O(N)。
  • 空间复杂度:
    • 递归过程中的栈空间复杂度为O(N),用于树的构建。
    • 层次遍历中的队列空间复杂度为O(N)。

Java

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * @author code5bug
 */
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        String postOrder = in.next(), inOrder = in.next();
        Solution solution = new Solution();
        TreeNode root = solution.build(postOrder, inOrder);

        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);

        StringBuilder rs = new StringBuilder();
        while (!q.isEmpty()) {
            TreeNode poll = q.poll();
            rs.append(poll.val);

            if (poll.left != null) q.offer(poll.left);
            if (poll.right != null) q.offer(poll.right);
        }
        System.out.println(rs.toString());
    }
}


class TreeNode {
    public char val;
    public TreeNode left, right;

    public TreeNode(char val) {
        this.val = val;
    }
}

class Solution {
    
    /**
     * 构建树
     *
     * @param postOrder 后序遍历
     * @param inOrder   中序遍历
     * @return
     */
    public TreeNode build(String postOrder, String inOrder) {
        int len = postOrder.length();
        if (len == 0) {
            return null;
        } else if (len == 1) {
            return new TreeNode(postOrder.charAt(0));
        }

        // 根节点值
        char rootVal = postOrder.charAt(len - 1);
        TreeNode root = new TreeNode(rootVal);

        // 根节点在中序遍历中的索引位置, 此位置用于拆分左右子树
        int pos = inOrder.indexOf(rootVal);
        String leftPostOrder = postOrder.substring(0, pos);
        String rightPostOrder = postOrder.substring(pos, len - 1);

        String leftInOrder = inOrder.substring(0, pos);
        String rightInOrder = inOrder.substring(pos + 1);

        // 构造左右子树
        root.left = build(leftPostOrder, leftInOrder);
        root.right = build(rightPostOrder, rightInOrder);
        return root;
    }
}

Python

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    def buildTree(self, postorder, inorder) -> TreeNode:
        """ 根据后续遍历和中序遍历构造树 """
        if not inorder:
            return None
        root = TreeNode(postorder[-1])
        pos = inorder.index(root.val)
        root.left = self.buildTree(postorder[:pos], inorder[:pos])
        root.right = self.buildTree(postorder[pos:-1], inorder[pos+1:])
        return root

    def levelOrder(self, root):
        """ 返回树的层次遍历结果 """
        res = []
        if not root:
            return res

        queue = [root]
        while queue:
            node = queue.pop(0)
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return ''.join(res)


if __name__ == '__main__':
    s = Solution()
    postorder, inorder = map(list, input().split())
    root = s.buildTree(postorder, inorder)
    print(s.levelOrder(root))

C++

#include <bits/stdc++.h>
using namespace std;

struct TreeNode
{
    char      val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(char x) : val(x), left(nullptr), right(nullptr) {}
};

/* 构建树 */
TreeNode* buildTree(string postorder, string inorder)
{
    if (postorder.empty()) return nullptr;

    TreeNode* root = new TreeNode(postorder.back());
    postorder.pop_back();

    int pos = inorder.find(root->val);

    root->left  = buildTree(postorder.substr(0, pos), inorder.substr(0, pos));
    root->right = buildTree(postorder.substr(pos), inorder.substr(pos + 1));

    return root;
}

/* 返回树的层次遍历结果 */
string levelOrder(TreeNode* root)
{
    string           res;
    queue<TreeNode*> q;
    if (root) q.push(root);
    while (!q.empty()) {
        TreeNode* node = q.front();
        q.pop();
        res += node->val;
        if (node->left) q.push(node->left);
        if (node->right) q.push(node->right);
    }
    return res;
}

int main()
{
    string postorder, inorder;
    cin >> postorder >> inorder;
    TreeNode* root = buildTree(postorder, inorder);
    cout << levelOrder(root) << endl;
    return 0;
}    

相关练习题

alt

希望这个专栏不仅能帮您成功通过华为机试,还能让您熟练掌握算法。

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

#面经##春招##秋招##校招##华为#
全部评论
大佬,Java开发 刷题是C卷还是D卷,近期要机考,麻烦啦。
点赞 回复 分享
发布于 2024-05-11 22:17 北京
大佬 请教下 测开岗 刷题是C卷还是D卷
点赞 回复 分享
发布于 2024-05-10 16:13 上海

相关推荐

重生我想学测开:嵌入式的问题,我准备入行京东外卖了
点赞 评论 收藏
分享
评论
3
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务