【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【DFS/BFS】2023C-二叉树的广度优先遍历【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例
      • 输入
      • 输出
      • 说明
  • 解题思路
    • 从中序与后序遍历构造二叉树
    • 二叉树的层序遍历
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

有一棵二叉树,每个节点由一个大写字母标识(最多26个节点),现有两组字母,分别表示后序遍历 (左孩子->右孩子->父节点) 和中序遍历 (左孩子->父节点->右孩子) 的结果,请输出层次遍历的结果。

输入描述

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

输出描述

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

示例

输入

CBEFDA CBAEDF

输出

ABDCEF

说明

二叉树为

    A
   / \
  B   D
 /   / \
C   E   F

解题思路

本题属于两道经典二叉树题目的结合

LeetCode106. 从中序与后序遍历构造二叉树 和 LeetCoe102. 二叉树的层序遍历

从中序与后序遍历构造二叉树

根节点A一定是后序遍历结果中的最后一个元素。即

CBEFD | A

可以在中序遍历中定位到根节点A,即

CB | A | EDF
     ↑
     根节点

在中序遍历结果中,根节点的左边和右边分别是其左子树和右子树中序遍历的结果,即

CB | A | EDF
↑         ↑
左子树    右子树

可以得知,根节点的左子树的节点个数为2,右子树的节点个数为3。反映到后序遍历上,有

CB | EFD | A
↑      ↑
左子树 右子树

由于中序遍历和后序遍历都是递归的,因此对于其左子树和右子树的中序和后序遍历结果,又可以继续上述过程。直到子树构建完毕。其代码为

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

def buildTree(inorder, postorder):
    dic = {val: i for i, val in enumerate(inorder)}
    n = len(inorder)
    return help(dic, postorder, inorder, n-1, 0, n-1)

def help(dic, postorder, inorder, post_end, in_start, in_end):
    if in_start > in_end:
        return None
    node_val = postorder[post_end]
    idx_node = dic[node_val]
    node = TreeNode(node_val)

    node.left = help(dic, postorder, inorder, post_end - (in_end - idx_node) - 1, in_start, idx_node - 1)
    node.right = help(dic, postorder, inorder, post_end - 1, idx_node + 1, in_end)

    return node

二叉树的层序遍历

层序遍历就是经典的二叉树BFS过程,直接套模板即可。

def level_order_traverse(root):
    ans = str()
    q = deque()
    q.append(root)
    while q:
        node = q.popleft()
        ans += node.val
        if node.left:
            q.append(node.left)
        if node.right:
            q.append(node.right)
    return ans

代码

Python

# 题目:【DFS&BFS】2023C-二叉树的广度优先搜索
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:DFS/BFS
# 代码看不懂的地方,请直接在群上提问


from collections import deque


# 构建树节点类
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None


def buildTree(inorder, postorder):
    dic = {val: i for i, val in enumerate(inorder)}
    n = len(inorder)
    # 递归入口
    return help(dic, postorder, inorder, n-1, 0, n-1)


# 对于任何一棵子树:
# 根节点node一定位于该子树后序遍历数组的最后一个位置post_end,即可以计算得到node_val
# 根据node_val可以找到根节点node在中序遍历数组中的位置,其左边为左子树,右边为右子树
# 然后对左子树和右子树进行递归操作
def help(dic, postorder, inorder, post_end, in_start, in_end):
    # 递归终止条件:若中序遍历区间不存在,返回空节点
    if in_start > in_end:
        return None
    # 获得当前区间的根节点的值node_val,为postorder[post_end]
    node_val = postorder[post_end]
    # 获得该节点在中序遍历数组中的值
    idx_node = dic[node_val]
    # 构建节点node
    node = TreeNode(node_val)

    # 分别对node_val的左边和右边进行递归,得到左节点和右节点
    node.left = help(dic, postorder, inorder, post_end - (in_end - idx_node) - 1, in_start, idx_node - 1)
    node.right = help(dic, postorder, inorder, post_end - 1, idx_node + 1, in_end)

    # 将该节点回传
    return node


# 对根节点为root的二叉树进行层序遍历的函数,
# 直接套二叉树BFS模板
def level_order_traverse(root):
    ans = str()
    q = deque()
    q.append(root)
    while q:
        node = q.popleft()
        ans += node.val
        if node.left:
            q.append(node.left)
        if node.right:
            q.append(node.right)
    return ans


# 输入后序、中序遍历的结果字符串
postorder, inorder = input().split()
# 建树
root = buildTree(inorder, postorder)
# 层序遍历
ans = level_order_traverse(root)
# 输出结果
print(ans)

Java

import java.util.*;

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

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

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String postorder = scanner.next();
        String inorder = scanner.next();

        TreeNode root = buildTree(inorder, postorder);
        String ans = levelOrderTraverse(root);
        System.out.println(ans);
    }

    public static TreeNode buildTree(String inorder, String postorder) {
        Map<Character, Integer> dic = new HashMap<>();
        for (int i = 0; i < inorder.length(); i++) {
            dic.put(inorder.charAt(i), i);
        }
        return help(dic, postorder.toCharArray(), inorder.toCharArray(), inorder.length() - 1, 0, inorder.length() - 1);
    }

    public static TreeNode help(Map<Character, Integer> dic, char[] postorder, char[] inorder, int postEnd, int inStart, int inEnd) {
        if (inStart > inEnd) {
            return null;
        }
        char nodeVal = postorder[postEnd];
        int idxNode = dic.get(nodeVal);
        TreeNode node = new TreeNode(nodeVal);

        node.left = help(dic, postorder, inorder, postEnd - (inEnd - idxNode) - 1, inStart, idxNode - 1);
        node.right = help(dic, postorder, inorder, postEnd - 1, idxNode + 1, inEnd);

        return node;
    }

    public static String levelOrderTraverse(TreeNode root) {
        StringBuilder ans = new StringBuilder();
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            ans.append(node.val);
            if (node.left != null) {
                q.offer(node.left);
            }
            if (node.right != null) {
                q.offer(node.right);
            }
        }
        return ans.toString();
    }
}

C++

#include 
#include 
#include 
using namespace std;

struct TreeNode {
    char val;
    TreeNode *left;
    TreeNode *right;

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

TreeNode *buildTree(unordered_map<char, int> &dic, string &postorder, string &inorder, int postEnd, int inStart, int inEnd) {
    if (inStart > inEnd) {
        return nullptr;
    }
    char nodeVal = postorder[postEnd];
    int idxNode = dic[nodeVal];
    TreeNode *node = new TreeNode(nodeVal);

    node->left = buildTree(dic, postorder, inorder, postEnd - (inEnd - idxNode) - 1, inStart, idxNode - 1);
    node->right = buildTree(dic, postorder, inorder, postEnd - 1, idxNode + 1, inEnd);

    return node;
}

string levelOrderTraverse(TreeNode *root) {
    string ans;
    queue<TreeNode *> q;
    q.push(root);
    while (!q.empty()) {
        TreeNode *node = q.front();
        q.pop();
        ans.push_back(node->val);
        if (node->left) {
            q.push(node->left);
        }
        if (node->right) {
            q.push(node->right);
        }
    }
    return ans;
}

int main() {
    string postorder, inorder;
    cin >> postorder >> inorder;

    unordered_map<char, int> dic;
    for (int i = 0; i < inorder.size(); ++i) {
        dic[inorder[i]] = i;
    }

    TreeNode *root = buildTree(dic, postorder, inorder, inorder.size() - 1, 0, inorder.size() - 1);
    string ans = levelOrderTraverse(root);
    cout << ans << endl;

    return 0;
}

时空复杂度

时间复杂度:O(N)。建树过程和层序遍历过程,均需遍历每一个节点。

空间复杂度:O(N)。哈希表所占空间。


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,DFS,#,BFS,算法,java,c++,python,华为od,leetcode,深度优先)