https://www.evernote.com/shard/s424/sh/2804d7e0-c93c-455d-9b79-027caa1750c5/48c247d32264b0e5739c5fc27c7eaff1
1 using System; 2 3 // To execute C#, please define "static void Main" on a class 4 // named Solution. 5 6 public class IdManager 7 { 8 private int maxId; 9 private bit[] buddyTree; 10 11 public IdManager(int maxId) 12 { 13 this.maxId = maxId; 14 this.buddyTree = new bit[2 * maxId]; 15 } 16 17 private bit findAvailableId(int rootIndex) 18 { 19 if ( 20 } 21 22 public int AllocateId() 23 { 24 if (bit[0] == 1) throw new FullException(); 25 26 int cur = 0; 27 28 while (cur < this.maxId) 29 { 30 int left = 2 * (cur + 1) - 1; 31 int right = 2 * (cur + 1); 32 33 if (bit[left] == 0) 34 { 35 cur = left; 36 } 37 else 38 { 39 cur = right; 40 } 41 } 42 43 bit[cur] = 0x1; 44 45 cur = cur % 2 == 1 ? cur : cur - 1; 46 47 while (bit[cur] == 1 && bit[cur + 1] == 1) 48 { 49 int p = cur / 2; 50 bit[p] = 1; 51 52 cur = p; 53 54 cur = cur % 2 == 1 ? cur : cur - 1; 55 } 56 57 return cur; 58 } 59 60 public void ReleaseId(int id) 61 { 62 availableIds.Add(id); 63 } 64 65 } 66 67 public class IdManager 68 { 69 private int maxId; 70 private HashSet<int> availableIds = new HashSet<int>(); 71 72 public IdManager(int maxId) 73 { 74 this.maxId = maxId; 75 76 for (int i = 0; i < maxId; i++) 77 { 78 availableIds.Add(i); 79 } 80 } 81 82 public int AllocateId() 83 { 84 int id = -1; 85 foreach (var k in availableIds) 86 { 87 id = k; 88 break; 89 } 90 91 availableIds.Remove(id); 92 93 return id; 94 } 95 96 public void ReleaseId(int id) 97 { 98 availableIds.Add(id); 99 } 100 101 } 102 103 104 class Solution 105 { 106 107 108 109 static void Main(string[] args) 110 { 111 for (var i = 0; i < 5; i++) 112 { 113 Console.WriteLine("Hello, World"); 114 } 115 } 116 }
電面, 第一輪 :
Leetcode -> Game of life: 不需要in place的解法。 follow up 是 如果數據很大,內存存不下怎么辦,需要寫代碼(可以自己假設已經存在文件讀寫的API)
電面, 第二輪 :
Leetcode -> Combination of phone number : 也是地里的面經題目。
onsite:
1. Remove Duplicate files 地里經典面經。
2. 實現一個網絡爬蟲,先寫單線程的版本,然后是多線程的版本,注意多線程版本如何控制結束條件。
3. 系統設計twitter。 需要設計app 端和server端怎么交互。(問的很細)
4. 實現 read write lock。(面試官 用的是 mutex) --> follow up, 怎么優化鎖,讀操作和寫操作很多的時候,怎么權衡。.
第一輪,三哥,game of life,寫完后問矩陣很大怎么辦,我說一行一行讀,然后寫了個一行行讀讀的代碼,java寫白板真是很慢。。。然后讓算了下每次內存占用多少,然后問問題結束了。
第二輪白人,問了個分配id的問題,范圍從1-n,寫兩個函數allocate和release。第二輪之前lz上了個廁所,然而不幸迷路,最終讓前台MM帶回,結果面試只有50min。lz和面試官討論了一下,寫了個N位bit的方法,寫完還剩15min,白人讓優化,但是說時間來不及了,你就說想法,然后就想到了用線段樹的方法,討論了下時間空間復雜度,期間讓算了下內存占用,然后問問題結束。
最后一輪,真的是很累了。白人,本來又問了那個分配id的題,我說這題第二輪問過了,換了個bitTorent的題,第一問很常規,很快寫出來了,分析了下復雜度,然后followup,很快又想出來了,但是讓優化,沒想出來,然后最后一看時間來不及了,匆忙寫了下我那個方法,后來被告知要用平衡樹。。。感覺這輪答的一般
一面:給一個文件和一個byte數組,判斷這個byte數組是否在文件里出現過?本質是字符串匹配,然而不同的是文件可能很大,不能一次性讀進內存。我是假設了一個常量表示了內存分配給我(要解釋為什么需要這個常量),創建一段buffer,一開始將它填滿,然后匹配buffer和byte數組(過程就和字符串匹配一樣,我是用最蠢的辦法),配不上的話,將最后的(byte數組長度-1)個byte移到buffer前端,然后繼續讀文件更新buffer剩下的部分,再次匹配,重復這個過程知道文件到尾或者匹配成功。寫完后出了兩個bug,在面試官提示下修復了,不是自己找出來的= = 然后是followup,提高時間效率,我說用KMP?他說我不期望你用KMP,那是有點research的方法。我又想了一下,他給我hint說你知道rollinghash嗎?我說不知道= =他就跟我簡單解釋了一下,就是一個byte數組有一個hash值,然后當刪除一個前端的byte或者添加一個新的byte在末尾的時候,可以通過運算在O(1)時間內算出新的hash值。然后就給我一個class rollinghash,三個方法addbyte,removebyte,hash,叫我根據這個改代碼。改完之后(這一次應該沒有bug了= =),他問我有什么好方法可以實現這個hash函數嗎(要求當然就是rollinghash這個類里的三個方法都是常數復雜度),不要求unique,但盡量要求不同?我說XOR每個byte?每個byte相加?他說可以,然后他說了一個他們在用的辦法:設一個常數a,假設byte數組是bytes[0:n-1],那么hash值為a^(n-1)*byte[n-1]+a^(n-2)*byte[n-2]+...+a^0*byte[0]
二面:經典買soda題,用dfs,要求改進,用dp,然后分析兩者復雜度。做的時候太困,傻不拉幾的,建議大家吃完午飯后喝咖啡。。當然因人而異哈
三面:二面之后喝了咖啡,復活了。實現一個分配id的類,id可以是0~MAX_ID-1中的一個值,分配出去的id必須唯一,類里面還有個回收id的函數,總而言之就是實現這個類的兩個函數allocate和dellocate,數組結構自己設計。我說了兩個方案,一個用queue,一個用bool數組。他讓我先討論用queue的情況,寫了代碼,用queue很直接,然后他讓改進時間和空間,方案就是用一個自增的整數,表示還沒被分配的id,初始化為0,再有一個隊列,每當dellocate時,就將這個回收的id放到一個隊列里。每當allocate時,先判斷這個隊列里有沒有id,有的話拿出來返回,沒有就拿那個整數,並另其+=1,這樣的話構造函數的復雜度就變成O(1)了,同時空間也省了很多。接着讓討論bool數組的情況,這個方法比較糟糕,初始化O(n),allocateO(n),唯一好處就是空間比queue省一點。然后他讓改進,想了一會無果,他提示有沒有辦法可以讓allocate更快呢,快32倍,快64倍。然后我就說用bit,每次我可以掃32位(int),然后如果這個int大於0的話,就說明這里面有一個id可用,然后就可以用常數級的方法找出這個id。他說還有沒有更快的,比如存儲一些臨時信息?我就基於前面的方法和這個hint想到了用線段樹,這樣的話,初始化O(n),allocateO(logn),dellocateO(logn),然后他讓我寫了代碼,假設線段樹已經建好了,要我實現allocate函數,pls note that 在實現的過程中,我假設一個數節點存着區間開始和結束點,可用id數量,左孩子和右孩子指針。寫完后他讓我優化空間,我說不需要開始和結束點,因為可以通過計算算出來。讓我再優化,我說可用id數量可以換成一個bool值。讓我再優化,讓我省去兩個指針,我說或許我可以用堆的數組實現方式來做,但是這不一定是一顆滿二叉樹,他說那假設maxid是2^n吧,我說那可以了,我只用一個數組就好了,a的左右孩子分別為a[2i+1],a[2i+2]。然后最終方案就變成了只需要2*MAX_ID-1個bit的空間來實現。總結一下就是用queue耗空間省時間,數組耗時間省空間。
1. id allocation/deallocation 先實作了queue的做法, 然後是bit array, 問是否有time/space complexity在兩個之間的方法。最後作了binary tree (each node stores whether there's any available ids in its subtrees) 有寫完,面試官很滿意
2. download bit-torrent. 第一題基本上就是merge intervals。後來是interval連續進入,寫了一個binary search找位置然後linear update. 寫完後考慮要問演算法(猜測是用樹來解這題)或是system,選了system.結果問如果真的download這些paritial file後要怎麼merge real files
3. Sharpness value. 一開始以為是新題,說要在一個image中找最像地平線的一條線。DP解。問如果圖太大怎麼處理,問各種讀法的disk access次數。期待的答案好像是把各種讀法的disk access次數寫成一個function然後找到最佳解
4. Behavior
5. Project deep dive
6. 照片每次被view就會call View(photo id), 給top-k view photo. 一開始假設有整個oracle, 用heap解決。延伸如果view是一個個來,寫了一個很複雜的heap + hashmap。期待的最佳解應該是bucket sort
第一輪coding:Allocate IDs 經典老題,給出三種解法,面試官很滿意
第二輪deep dive:畢竟工作四年多了,這輪發揮正常,把之前做的project挑出幾個方面講一講
第三輪lunch:跟一個ABC小哥,聊的很愉快
第四輪coding: Web crawler + 多線程版。也是面經原題,就是吃完飯有點兒困,被找出來倆bug。。。. 1point 3acres 璁哄潧
第五輪All rounds:就是behavior questions,各種問平時工作中的困難啊,交流啊,什么情況應該怎么辦啊。面試感覺中規中矩。
第六輪architecture: 設計一個upload file 到S3 還要通過thumbnail server把這個file做thumbnail的系統。我面完就覺得可能要跪在這一輪了,面試官問的非常非常仔細,各種某一部分down了應該怎么辦啊,怎么提高用戶體驗啦之類的。。。。盡力答了,但是到最后有倆模塊的處理還沒答完。
.1. Game of lives, 輸入: 給一個matrix的grid, 每個的值是Live or Dead, 輸出: 一個同樣大小的matrix, 每個的值設定如下:
如果目前值是live, 而且周圍8個grid中, live的數量是2 or 3, 則變成dead. more info on 1point3acres.com
如果目前值是dead, 周圍8個grid中, live數量是3, 變成live
followup: 盡量減少內存開銷, 該怎么做.
2. 見過: 買罐裝汽水,只能一罐一罐或者一箱一箱地買。箱子有幾種不同大小,比如一箱12罐,一箱6罐, 一箱2, 一箱1 等等。這個input是個list。讓輸出所有買法(就是每種package買幾個這樣)
用recursive解了
followup: 如果剪紙
3. 老題目: 返回一個文件系統里面的duplicate files
4. 老題目: 設計一個web crawler, 多線程版本
5. 給出一堆log, 里面有photo id和訪問時間, 還有一個iterator, 能夠按照photoId 和訪問時間iterate, 問如何輸出top m的訪問photo
followup: 如何存儲這些log, 來支持方便的retrieve 這些信息.
6. Project deep dive.
7. Behavior questions, hard project, motivation, blablabla...