目錄
前言
七月收穫了位元組的意向書,今日得空把面經整理出來分享給大家,也藉此把好運分享給大家。
簡單介紹下個人情況:
面試前:劍指 offer 刷完,Leetcode 大概 70 道。作業系統複習完畢,資料庫不會,計網不會。
後來:一面前一週學了資料庫,三面前三天學了計網。兩週時間陸續刷了 80 道 Leetcode。
希望這篇文章能對大家有所幫助,祝各位 offer 多多!
三輪面經
本人無實習,故而沒有被問到關於專案的問題。
問題構成:手撕程式碼、基礎知識、場景題。
「基礎知識」都是固定答案,因此本篇中只分享題目,不分享答案。
一面
手撕程式碼
easy 題:中文字串轉成數字。例:“五百三十萬六千零三” -> 5306003。約束:輸入金額在一億以內。要求:做一定的容錯處理,bug free。
這題比較簡單,方法大家應該都能想到。只是要求 bug free 和容錯處理,因此寫程式碼的時候要考慮完善點。比如說輸入異常的情況(字串是否合法,“五五百”這種就不合法,“3百五”也不合法)。
手撕程式碼
leetcode medium 原題:判斷字串是否滿足斐波那契規則,如:“199100199”。由於 1 + 99 = 100,99 + 100 = 199。
這題老汪是在面試官的引導下才一步一步想到最優解的。(吹爆面試體驗,面試官很耐心的在引導,nice!)
這題的關鍵點就在於如何找到開頭兩個數字 n1, n2。找到了這兩個數字,後面就可以用 n = n1 + n2 的規則通過一次遍歷來判斷是否符合斐波那契規則。找開頭倆數字只能暴搜了,程式碼如下:
public boolean solve(String str){
if(str == null) return false;
int n = str.length();
for(int i = 1; i < n; i++){
int n1 = Integer.parseInt(str.substring(0, i)); //獲得第一個數
for(int j = i + 1; j < n; j++){
int n2 = Integer.parseInt(str.substring(i, j)); //獲得第二個數
if(judege(str, n1, n2, start)) return true;//判斷是否符合規則
}
}
return false;
}
//給定 n1, n2,判斷字串是否符合斐波那契規則
boolean judge(String str, int n1, int n2, int start){
int n = str.length();
for(int i = start; i < n;){
int n3 = n1 + n2;
int len = (n3 + "").length();
if(start + len > n || n3 != Integer.parseInt(str.substring(i, i + len))) return false; // 下標超了,或者後一個數字不等於 n3
i += len;
}
return true;
}
時間複雜度:O(n^3),找到開頭兩個數字需要 O(n^2),判斷字串是否符合規則需要 O(n)。
這題可以剪枝來稍微降低一些時間消耗,大家可以自行優化。
手撕程式碼
10億個無序整數找出中位數。
這題老汪也是在面試官的引導下才一步步想到最優解的。(再次吹爆面試體驗)
由於是 10 億個整數,因此無法在記憶體中處理。也就是說要採用合適的外排序演算法。
這裡可以使用桶排序,使用 n 個區間均勻的桶,遍歷一遍整數,將它們存入對應區間的桶中,並統計桶中數字個數。這樣就可以找到中位數所在的桶,如果桶中數字還是很多,再進行桶排序,否則進記憶體中排序即可。
二面
事務的 ACID 特性
Innodb 使用的索引結構
b+ tree 的優點,為什麼要用它
給定複合索引 (a, b, c),查詢語句中用 where a = 1 and c = 1,索引是否會失效?(最左字首匹配的相關知識)
一條 SQL 語句的執行流程 (不會)
程式和執行緒的區別
併發和並行的區別
程式排程的策略
死鎖發生的原因
leetcode 原題 41 (不會,換了一題)
給你一個未排序的整數陣列,請你找出其中沒有出現的最小的正整數。
思路:要找最小的正整數,陣列中有 n 個數字,那麼缺失的最小正整數一定在 [1, n + 1] 內。
因此可以利用陣列本身做雜湊,遍歷一遍陣列,將 [1, n] 內的數字 i
放到對應下標 i - 1
上。
再遍歷一遍陣列,第一個 nums[i] != i + 1
的數字 i + 1即為缺失的最小正整數。
程式碼如下:
public int firstMissingPositive(int[] nums) {
int n = nums.length;
for(int i = 0; i < n; i++){
while(nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]){ //(0, n] 的數字放到對應下標上
int temp = nums[i] - 1;
nums[i] = nums[temp];
nums[temp] = temp + 1;
}
}
int i = 0;
for(; i < n && nums[i] == i + 1; i++); // 找到第一個未出現的正整數
return i + 1;
}
時間複雜度:O(n),雖然有 while 迴圈,但每個數字最多被交換一次即可到對應下標上。
leetcode 原題 3
給定一個字串,請你找出其中不含有重複字元的 最長子串 的長度。
思路:很經典的一道題了,滑動視窗即可解決。
程式碼如下:
public int lengthOfLongestSubstring(String s) {
if(s == null) return 0;
Map<Character, Integer> map = new HashMap<>();
int start = 0, ans = 0;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(map.getOrDefault(c, -1) >= start) start = map.get(c) + 1;
map.put(c, i);
ans = Math.max(ans, i - start + 1);
}
return ans;
}
三面
手撕程式碼
演算法題:二維陣列,按行遞增,按列遞增,問是否能找到某個數字(劍指offer原題)
思路:利用遞增的特性,從最左下角開始遍歷(該列最大值,該行最小值)。和目標數字比較:
< 目標數
,說明這一列都 < 目標數,因此列下標 + 1
> 目標數
,說明這一行都 > 目標數,因此行下標 - 1
這樣,每次比較都可以排除一行/一列。
程式碼如下:
public boolean canFind(int[][] matrix, int target){
if(matrix == null || matrix.length == 0) return false;
int rows = matrix.length, cols = matrix[0].length;
int row = rows - 1, col = 0;
while(row >= 0 && col < cols){
if(matrix[row][col] == target) return true;
if(matrix[row][col] > target) row--;
else col++;
}
return false;
}
手撕程式碼
演算法題:
2 * 1
的小矩形填充滿2 * n
的大矩形有多少種方案?
思路:挺簡單的動態規劃題
程式碼如下:
public int nums(int n){
if(n < 0) return 0;
int[] dp = new int[Math.max(n, 2)];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i < n; i++) dp[i] = dp[i - 2] + dp[i - 1];
return dp[n];
}
這裡空間複雜度是 O(n),也可以通過 狀壓 dp
將空間複雜度降到 O(1)。
場景設計
1000 億個無符號整數,找最大的 100 個。記憶體不夠的情況下用什麼方案?記憶體充足的情況下呢? partition 的方案不穩定,有什麼穩定的方法嗎?
記憶體不夠堆排序,記憶體夠用計數排序。
https 如何加密的
os 中的 pagefault (缺頁中斷)
mysql 中的底層索引結構?為什麼用這個結構
hashmap 是執行緒安全的嗎?想要執行緒安全怎麼辦?
場景設計
大檔案的斷點續傳
這題網上也有很多方案。老汪是參照 tcp 的滑動視窗和重傳機制來回答的。
把大檔案分塊並打上編號,接收端對塊進行有序確認,如果有某塊沒收到,就告知傳送端讓其重發。
傳送端記錄最後一次傳送的編號,斷點續傳時從這個編號開始傳。
因為負載均衡,續傳的時候要確定從哪個伺服器拿的,這個可以讓接收端記錄傳送端的標識。
關於位元組
工作強度:大小周,10 10 5.5。不強制加班,做完就可以走,但工作量一般要加班完成。因人而異,也有摸魚的。
福利:三餐全包,下午茶,房補 1500,免費健身房(基本上工作一年後都會吃胖,hhh)
氛圍:扁平化管理,網傳風評都挺不錯的。
新人培養:mentor 制,一對一帶領新人熟悉。不過和老牌 BAT 相比,文件不夠完善,新人培養流程還是有些欠缺的。
位元組校招的考察重點:後端的話,基本上是要轉 go/python 的,所以不怎麼考察語言。
主要考察「作業系統」、「資料庫原理」、「計網」和「手撕程式碼」,位元組是非常重視手撕的,這個一定要好好準備。當然專案做得好的同學,也是有加分的。
老汪點評:工作強度大,面對的挑戰多,薪酬也給力。適合能力強、抗壓能力強的同學,扛得住壓成長會很快。不過對新人確實有點考驗,因人而異吧。
彩蛋
雖然位元組的手撕程式碼比較難,但題庫是有限的,多刷面經中的演算法題,會有很大概率碰上原題。 有三面掛了的,想投上海 data 部門的,老汪可以幫忙聯絡 HR 直撈。 祝點贊的各位小夥伴 offer 多多。沒點讚的小夥伴嘛,也 offer 多多吧。嘻嘻~ 聽說發一句 “一切都會好起來的!”,就真的一切都好起來了!