笔试 | 字节跳动2021秋招笔试第二场 题目&解法

文章首发于公众号“面鲸“,欢迎关注~I’m waiting for you!

第一题

题目描述
  • 给定一颗二叉树,二叉树每个节点都有唯一的正整数值代表节点,在遍历时,我们使用节点的数值作为标记。给定二叉树的前序和中序遍历结果,求二叉树的叶子节点个数。
输入
  • 第一行,输入二叉树节点个数N,其中0 < N < 30000
  • 第二行与第三行,分别输入二叉树的前序和中序遍历结果,每个节点对应唯一整数值
输出
  • 二叉树叶子节点个数
样例输入
  • 3
  • 1 3 4
  • 3 1 4
样例输出
  • 2
分析
  • 这是leetcode一个经典的题的拓展:给定一个二叉树的前序和中序遍历,让你重构一个二叉树。如果leetcod这个题会的话只需要简单加个统计就能解出字节这个题了。
  • 大概的思路就是用递归的方法。利用这个关键信息:前序遍历的第一个节点一定是根节点root,而在中序遍历中root节点左侧的节点一定是它左子树的所有节点。
  • 对于这个题的话,我们其实没必要去重构二叉树。当我们在重构的过程中发现root左侧的节点只有一个的时候,那么它左侧的这个节点一定是叶子节点。右侧的节点同理。
解法
#include <bits/stdc++.h>

using namespace std;

const int maxn = 30001;
int ans;
vector<int> pre(maxn, 0), mid(maxn, 0);

// 当前树的所有节点,在前序序列中的范围是[l, r],在中序序列中的范围是[ml, mr]
void dfs(int l, int r, int ml, int mr) {
   
    if (l > r) return; // 当前树没节点了
    if (l == r) {
    // 如果这个树只有一个节点,那它肯定是叶子节点
        ans++;
        return;
    }
    int root = pre[l]; // 当前树的跟节点
    int index;
    for (int i = ml; i <= mr; ++i) {
    // 在中序序列中找这个树的左子树范围和右子树范围
        if (mid[i] == root) {
   
            index = i;
            break;
        }
    }
    int lcnt = index - ml; // 左子树的节点数,利用中序序列中root节点左侧的是左子树,右侧的是右子树
    int rcnt = mr - index; // 右子树的节点树
    dfs(l + 1, l + lcnt, ml, index - 1); // 递归处理左子树,下同
    dfs(l + lcnt + 1, r, index + 1, mr);
}

int main() {
   
    int n;
    while(cin >> n) {
   
        for (int i = 1; i <= n; ++i) cin >> pre[i];
        for (int i = 1; i <= n; ++i) cin >> mid[i];
        ans = 0;
        dfs(1, n, 1, n);
        cout << ans << endl;
    }
    return 0;
}

n = int(input())
pre = input().split()
mid = input().split()

ans = 0

def dfs(l, r, ml, mr):
    global ans
    if l > r: return
    if l == r:
        ans += 1
        return
    root = pre[l]
    index = ml
    for i in range(ml, mr + 1):
        if mid[i] == root:
            index = i
            break
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值