字節(jié)跳動抖音社招后臺開發(fā)工程師面經(jīng)

最近參加了字節(jié)跳動的后臺開發(fā)工程師面試如失,記錄一下面經(jīng)。(ps:社招兩年經(jīng)驗(yàn))

1. 一面(1小時)

一面主要是基礎(chǔ)考察送粱,包括簡歷中提到的以及一些標(biāo)準(zhǔn)的基礎(chǔ)問題复斥。

  1. VUE和React區(qū)別(因?yàn)楹啔v中提到了VUE)

  2. VUE的內(nèi)部機(jī)制(問一下前端技術(shù)是因?yàn)槲液啔v提到自己是全棧工程師嘁捷,正常情況下是不會出現(xiàn)前端問題的)

  3. CRSF的機(jī)制

  4. Spring IOC和BEAN循環(huán)依賴

  5. Kafka和Cassandra內(nèi)部機(jī)制(簡歷中提及)

  6. 算法題:有 2n 個人,序號為 0 到 2n-1,要求兩兩握手惨缆,但是握手不能存在交叉線,求最后一
    共存在多少種握手可能捧弃,寫出 f(2n)表達(dá)式拿诸。

思路:假設(shè)0號和i號點(diǎn)握手,那么整張圖就分為了0 ~ i-1和i+1 ~ 2n這兩部分洽胶。

  1. 算法題:給定一個二維整數(shù)矩陣晒夹,找出最長遞增路徑的長度。對于每個單元格姊氓,你可以往上丐怯,下,左翔横,右四個方向移動读跷。 你不能在對角線方向上移動或移動到邊界外(即不允許環(huán)繞)。

思路:記憶化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. 在另一個事業(yè)部一面時禾唁,遇到了三個水壺的問題:三個水壺效览,粉筆為 8L,3L荡短,5L丐枉,給一個 num,判斷能否量出這個指定 num 的水掘托。

思路:BFS窮舉所有可能性瘦锹,直到出現(xiàn)目標(biāo)水量。

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. 項目介紹(半小時)

準(zhǔn)備好一些工作中解決的問題闪盔,盡可能詳細(xì)的闡述給面試官弯院,告訴他你主要解決了什么問題。

  1. 系統(tǒng)設(shè)計題:上海地鐵線縱橫交錯(線路與線路之間存在交叉泪掀,并且每一條線路站與站之間的發(fā)車間隔可能是不一樣的)听绳,現(xiàn)在做一個 app,輸入是起點(diǎn)和終點(diǎn)已經(jīng)出發(fā)時間异赫,輸出一條耗時最短的線路椅挣。

從數(shù)據(jù)庫表头岔,到緩存,到算法的設(shè)計贴妻。

3. 三面(40分鐘)

三面是抖音上海負(fù)責(zé)人的面試切油,因此著重在系統(tǒng)設(shè)計。

  1. 項目介紹(15分鐘)

  2. 系統(tǒng)設(shè)計:抖音里每秒都產(chǎn)生大量視頻名惩,現(xiàn)在要求持續(xù)計算一段時間內(nèi)的 top k 個最熱門的視頻澎胡,你怎么設(shè)計。

這個問題類似于下面這個問題:

實(shí)現(xiàn)前5分鐘娩鹉,1小時攻谁,24小時內(nèi)分享最多的feed

從算法的角度,可以簡單的稱之為 Top K Frequent Elements in Recent X mins弯予。算法的角度戚宦,本質(zhì)就是設(shè)計一個數(shù)據(jù)結(jié)構(gòu),支持給某個key的count+1(有一個post被分享了)锈嫩,給某個key的count-1(有一個分享的計數(shù)已經(jīng)過期了)受楼,然后查詢Top k。

做法是維護(hù)一個有序序列(用鏈表來維護(hù))呼寸,每個鏈表的節(jié)點(diǎn)的key是 count艳汽,value是list of elements that has this count,也用linked list串起來对雪。 比如 a出現(xiàn)2次河狐,b出現(xiàn)3次,c出現(xiàn)2次瑟捣,d出現(xiàn)1次馋艺。那么這個鏈表就是:

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

然后另外還需要一個hashmap,key是element迈套,value是這個element在鏈表上的具體位置捐祠。
因?yàn)槊恳淮蔚牟僮鞫际?count + 1和 count - 1,那么每次你通過 hashmap 找到對應(yīng)的element在數(shù)據(jù)結(jié)構(gòu)中的位置桑李,+1的話踱蛀,就是往頭移動一格,-1的話芙扎,就是往尾巴移動一格√畲螅總而言之復(fù)雜度都是 O(1)戒洼。當(dāng)你需要找 Top K 的時候,也是 O(k)的時間可以解決的允华。

算法實(shí)現(xiàn)請參考:https://github.com/cheergoivan/leetcode/blob/master/src/leetcode/problem460/LFUCache.java

工程角度的優(yōu)化:

如果我要去算最近5分鐘的數(shù)據(jù)圈浇,我就按照1秒鐘為一個bucket的單位寥掐,收集最近300個buckets里的數(shù)據(jù)。如果是統(tǒng)計最近1小時的數(shù)據(jù)磷蜀,那么就以1分鐘為單位召耘,收集最近60個Buckets的數(shù)據(jù),如果是最近1天褐隆,那么就以小時為單位污它,收集最近24小時的數(shù)據(jù)。那么也就是說庶弃,當(dāng)來了一個某個帖子被分享了1次的數(shù)據(jù)的時候衫贬,這條數(shù)據(jù)被會分別存放在當(dāng)前時間(以秒為單位),當(dāng)前分鐘歇攻,當(dāng)前小時的三個buckets里固惯,用于服務(wù)之后最近5分鐘,最近1小時和最近24小時的數(shù)據(jù)統(tǒng)計缴守。

你可能會疑惑葬毫,為什么要這么做呢?這么做有什么好處呢屡穗?這樣做的好處是贴捡,比如你統(tǒng)計最近1小時的數(shù)據(jù)的時候,就可以隨著時間的推移鸡捐,每次增加當(dāng)前分鐘的所有數(shù)據(jù)的統(tǒng)計栈暇,然后扔掉一小時里最早的1分鐘里的所有數(shù)據(jù)。這樣子就不用真的一個一個的+1或者-1了箍镜,而是整體的 +X 和 -X源祈。當(dāng)然,這樣做之后色迂,前面的算法部分提出來的數(shù)據(jù)結(jié)構(gòu)就不work了香缺,但是可以結(jié)合下面提到的數(shù)據(jù)抽樣的方法,來減小所有候選 key 的數(shù)目歇僧,然后用普通的 Top K 的算法來解決問題图张。

另外,在分布式環(huán)境下诈悍,哪些帖子被分享了多少次這些數(shù)據(jù)祸轮,首先在 web server 中進(jìn)行一次緩存,也就是說web server的一個進(jìn)程接收到一個分享的請求之后侥钳,比如 tweet_id=100 的tweet被分享了适袜。那么他把這個數(shù)據(jù)先匯報給web server上跑著的 agent 進(jìn)程,這個agent進(jìn)程在機(jī)器剛啟動的時候舷夺,就會一直運(yùn)行著苦酱,他接受在臺web server上跑著的若干個web 進(jìn)程(process) 發(fā)過來的 count +1 請求售貌。

這個agent整理好這些數(shù)據(jù)之后,每隔510秒?yún)R報給中心節(jié)點(diǎn)疫萤。這樣子通過510s的數(shù)據(jù)延遲颂跨,解決了中心節(jié)點(diǎn)訪問頻率過高的問題。

還可以通過數(shù)據(jù)抽樣進(jìn)行優(yōu)化扯饶。因?yàn)槟切㏕op K 的post恒削,一定是被分享了很多很多次的,所以可以進(jìn)行抽樣記錄帝际。如果是5分鐘以內(nèi)的數(shù)據(jù)蔓同,就不抽樣,全記錄蹲诀。如果是最近1小時斑粱,就可以按照比如 1/100 的概率進(jìn)行 sample。

最后是使用Cache進(jìn)行緩存計算結(jié)果脯爪。對于最近5分鐘的結(jié)果则北,每隔5s才更新一次。對于最近1小時的結(jié)果痕慢,每隔1分鐘更新一次尚揣。對于最近24小時的結(jié)果,每隔10分鐘才更新一次掖举。用戶需要看結(jié)果的時候快骗,永遠(yuǎn)看的是 Cache 里的結(jié)果。另外用一個進(jìn)程按照上面的更新頻率去逐漸更新Cache塔次。

總結(jié):算法方面使用LFU算法來解決方篮。而工程方面使用分段統(tǒng)計,抽樣法和Cache緩存進(jìn)行優(yōu)化励负。

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

4. 總結(jié)

  1. 網(wǎng)絡(luò)和操作系統(tǒng)需要復(fù)習(xí)藕溅,復(fù)習(xí)一些常見的網(wǎng)上都能搜到的字節(jié)考題就行,不用太深入继榆。

  2. 算法 leetcode 刷 200~300 道差不多了巾表,另外面試前搜一下字節(jié)考過的算法題,很有可能遇到相同的略吨。

  3. 系統(tǒng)設(shè)計題就看平時積累集币,有想法就說出來,即使不是最優(yōu)解也要說出來翠忠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞠苟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌偶妖,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件政溃,死亡現(xiàn)場離奇詭異趾访,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)董虱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門扼鞋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人愤诱,你說我怎么就攤上這事云头。” “怎么了淫半?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵溃槐,是天一觀的道長。 經(jīng)常有香客問我科吭,道長昏滴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任对人,我火速辦了婚禮谣殊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牺弄。我一直安慰自己姻几,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布势告。 她就那樣靜靜地躺著蛇捌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪培慌。 梳的紋絲不亂的頭發(fā)上豁陆,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機(jī)與錄音吵护,去河邊找鬼盒音。 笑死,一個胖子當(dāng)著我的面吹牛馅而,可吹牛的內(nèi)容都是我干的祥诽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓮恭,長吁一口氣:“原來是場噩夢啊……” “哼雄坪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屯蹦,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤维哈,失蹤者是張志新(化名)和其女友劉穎绳姨,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阔挠,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飘庄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了购撼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跪削。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖迂求,靈堂內(nèi)的尸體忽然破棺而出碾盐,到底是詐尸還是另有隱情,我是刑警寧澤揩局,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布毫玖,位于F島的核電站,受9級特大地震影響凌盯,放射性物質(zhì)發(fā)生泄漏孕豹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一十气、第九天 我趴在偏房一處隱蔽的房頂上張望励背。 院中可真熱鬧,春花似錦砸西、人聲如沸叶眉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衅疙。三九已至,卻和暖如春鸳慈,著一層夾襖步出監(jiān)牢的瞬間饱溢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工走芋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绩郎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓翁逞,卻偏偏與公主長得像肋杖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挖函,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容