字节跳动抖音社招后台开发工程师面经

最近参加了字节跳动的后台开发工程师面试,记录一下面经。(ps:社招两年经验)

1. 一面(1小时)

一面主要是基础考察,包括简历中提到的以及一些标准的基础问题。

  1. VUE和React区别(因为简历中提到了VUE)

  2. VUE的内部机制(问一下前端技术是因为我简历提到自己是全栈工程师,正常情况下是不会出现前端问题的)

  3. CRSF的机制

  4. Spring IOC和BEAN循环依赖

  5. Kafka和Cassandra内部机制(简历中提及)

  6. 算法题:有 2n 个人,序号为 0 到 2n-1,要求两两握手,但是握手不能存在交叉线,求最后一
    共存在多少种握手可能,写出 f(2n)表达式。

思路:假设0号和i号点握手,那么整张图就分为了0 ~ i-1和i+1 ~ 2n这两部分。

  1. 算法题:给定一个二维整数矩阵,找出最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。

思路:记忆化DFS

public class Solution {
    private static final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

    public int longestIncreasingPath(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return 0;
        }
        int m = matrix.length, n = matrix[0].length;
        int[][] cache = new int[m][n];
        int res = 1;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                res = Math.max(res, dfs(matrix, i, j, cache));
            }
        }
        return res;
    }

    private int dfs(int[][] matrix, int i, int j, int[][] cache) {
        if (cache[i][j] != 0) {
            return cache[i][j];
        }
        int max = 1;
        int m = matrix.length, n = matrix[0].length;
        for (int[] dir : dirs) {
            int x = i + dir[0], y = j + dir[1];
            if (x >= 0 && x < m && y >= 0 && y < n && matrix[i][j] > matrix[x][y]) {
                max = Math.max(max, 1 + dfs(matrix, x, y, cache));
            }
        }
        cache[i][j] = max;
        return max;
    }
}
  1. 在另一个事业部一面时,遇到了三个水壶的问题:三个水壶,粉笔为 8L,3L,5L,给一个 num,判断能否量出这个指定 num 的水。

思路:BFS穷举所有可能性,直到出现目标水量。

public class ThreeBottles {

    private int[] capacity;

    public ThreeBottles() {
        capacity = new int[] { 8, 5, 3 };
    }

    public boolean canMeasure(int n) {
        Set<Integer> visited = new HashSet<>();
        Queue<Integer> queue = new LinkedList<>();
        int initialState = getState(new int[] { 8, 0, 0 });
        queue.add(initialState);
        visited.add(initialState);
        while (!queue.isEmpty()) {
            int state = queue.poll();
            if (match(state, n)) return true;
            int[] water = getWater(state);
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    int next = transfer(i, j, water);
                    if (next != -1 && !visited.contains(next)) {
                        queue.add(next);
                        visited.add(next);
                    }
                }
            }
        }
        return false;
    }

    private int getState(int[] water) {
        return water[0] << 8 | water[1] << 4 | water[2];
    }

    private int[] getWater(int state) {
        return new int[] { state >>> 8 & 15, state >>> 4 & 15, state & 15 };
    }

    private boolean match(int state, int n) {
        return (state >>> 8 & 15) == n || (state >>> 4 & 15) == n || (state & 15) == n;
    }

    private int transfer(int i, int j, int[] water) {
        int[] next = new int[] { water[0], water[1], water[2] };
        if (i != j && water[i] > 0 && water[j] < capacity[j]) {
            int transmission = Math.min(water[i], capacity[j] - water[j]);
            next[i] -= transmission;
            next[j] += transmission;
            return getState(next);
        }
        return -1;
    }
}

2. 二面(1小时)

  1. 项目介绍(半小时)

准备好一些工作中解决的问题,尽可能详细的阐述给面试官,告诉他你主要解决了什么问题。

  1. 系统设计题:上海地铁线纵横交错(线路与线路之间存在交叉,并且每一条线路站与站之间的发车间隔可能是不一样的),现在做一个 app,输入是起点和终点已经出发时间,输出一条耗时最短的线路。

从数据库表,到缓存,到算法的设计。

3. 三面(40分钟)

三面是抖音上海负责人的面试,因此着重在系统设计。

  1. 项目介绍(15分钟)

  2. 系统设计:抖音里每秒都产生大量视频,现在要求持续计算一段时间内的 top k 个最热门的视频,你怎么设计。

这个问题类似于下面这个问题:

实现前5分钟,1小时,24小时内分享最多的feed

从算法的角度,可以简单的称之为 Top K Frequent Elements in Recent X mins。算法的角度,本质就是设计一个数据结构,支持给某个key的count+1(有一个post被分享了),给某个key的count-1(有一个分享的计数已经过期了),然后查询Top k。

做法是维护一个有序序列(用链表来维护),每个链表的节点的key是 count,value是list of elements that has this count,也用linked list串起来。 比如 a出现2次,b出现3次,c出现2次,d出现1次。那么这个链表就是:

{3: [b]} --> {2: [a ->c]} --> {1: [d]}

然后另外还需要一个hashmap,key是element,value是这个element在链表上的具体位置。
因为每一次的操作都是 count + 1和 count - 1,那么每次你通过 hashmap 找到对应的element在数据结构中的位置,+1的话,就是往头移动一格,-1的话,就是往尾巴移动一格。总而言之复杂度都是 O(1)。当你需要找 Top K 的时候,也是 O(k)的时间可以解决的。

算法实现请参考:https://github.com/cheergoivan/leetcode/blob/master/src/leetcode/problem460/LFUCache.java

工程角度的优化:

如果我要去算最近5分钟的数据,我就按照1秒钟为一个bucket的单位,收集最近300个buckets里的数据。如果是统计最近1小时的数据,那么就以1分钟为单位,收集最近60个Buckets的数据,如果是最近1天,那么就以小时为单位,收集最近24小时的数据。那么也就是说,当来了一个某个帖子被分享了1次的数据的时候,这条数据被会分别存放在当前时间(以秒为单位),当前分钟,当前小时的三个buckets里,用于服务之后最近5分钟,最近1小时和最近24小时的数据统计。

你可能会疑惑,为什么要这么做呢?这么做有什么好处呢?这样做的好处是,比如你统计最近1小时的数据的时候,就可以随着时间的推移,每次增加当前分钟的所有数据的统计,然后扔掉一小时里最早的1分钟里的所有数据。这样子就不用真的一个一个的+1或者-1了,而是整体的 +X 和 -X。当然,这样做之后,前面的算法部分提出来的数据结构就不work了,但是可以结合下面提到的数据抽样的方法,来减小所有候选 key 的数目,然后用普通的 Top K 的算法来解决问题。

另外,在分布式环境下,哪些帖子被分享了多少次这些数据,首先在 web server 中进行一次缓存,也就是说web server的一个进程接收到一个分享的请求之后,比如 tweet_id=100 的tweet被分享了。那么他把这个数据先汇报给web server上跑着的 agent 进程,这个agent进程在机器刚启动的时候,就会一直运行着,他接受在台web server上跑着的若干个web 进程(process) 发过来的 count +1 请求。

这个agent整理好这些数据之后,每隔510秒汇报给中心节点。这样子通过510s的数据延迟,解决了中心节点访问频率过高的问题。

还可以通过数据抽样进行优化。因为那些Top K 的post,一定是被分享了很多很多次的,所以可以进行抽样记录。如果是5分钟以内的数据,就不抽样,全记录。如果是最近1小时,就可以按照比如 1/100 的概率进行 sample。

最后是使用Cache进行缓存计算结果。对于最近5分钟的结果,每隔5s才更新一次。对于最近1小时的结果,每隔1分钟更新一次。对于最近24小时的结果,每隔10分钟才更新一次。用户需要看结果的时候,永远看的是 Cache 里的结果。另外用一个进程按照上面的更新频率去逐渐更新Cache。

总结:算法方面使用LFU算法来解决。而工程方面使用分段统计,抽样法和Cache缓存进行优化。

以上方案参考自:https://www.jiuzhang.com/qa/219/

4. 总结

  1. 网络和操作系统需要复习,复习一些常见的网上都能搜到的字节考题就行,不用太深入。

  2. 算法 leetcode 刷 200~300 道差不多了,另外面试前搜一下字节考过的算法题,很有可能遇到相同的。

  3. 系统设计题就看平时积累,有想法就说出来,即使不是最优解也要说出来。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容