[譯] Google Interview University 一套完整的學習手冊幫助自己準備 Google 的面試
- 原文地址:Google Interview University
- 原文作者:John Washam
- 譯文出自:掘金翻譯計劃
- 譯者:Aleen,Newton,bobmayuze,Jaeger,sqrthree
這是?
這是我爲了從 web 開發者(自學、非計算機科學學位)蛻變至 Google 軟件工程師所制定的計劃,其內容歷時數月。
這一長列表是從 Google 的指導筆記 中萃取出來並進行擴展。因此,有些事情你必須去了解一下。我在列表的底部添加了一些額外項,用於解決面試中可能會出現的問題。這些額外項大部分是來自於 Steve Yegge 的“得到在 Google 工作的機會”。而在 Google 指導筆記的逐字間,它們有時也會被反映出來。
目錄
- 這是?
- 爲何要用到它?
- 如何使用它
- 擁有一名 Googler 的心態
- 我得到了工作嗎?
- 跟隨着我
- 不要自以爲自己不夠聰明
- 關於 Google
- 相關視頻資源
- 面試過程 & 通用的面試準備
- 爲你的面試選擇一種語言
- 在你開始之前
- 你所看不到的
- 日常計劃
- 必備知識
- 算法複雜度 / Big-O / 漸進分析法
- 數據結構
- 更多的知識
- 樹(Trees)
- 排序
- 圖(Graphs)
- 更多知識
- 終面
- 書籍
- 編碼練習和挑戰
- 當你臨近面試時
- 你的簡歷
- 當面試來臨的時候
- 問面試官的問題
- 當你獲得了夢想的職位
—————- 下面的內容是可選的 —————-
爲何要用到它?
我一直都是遵循該計劃去準備 Google 的面試。自 1997 年以來,我一直從事於 web 程序的構建、服務器的構建及創業型公司的創辦。對於只有着一個經濟學學位,而不是計算機科學學位(CS degree)的我來說,在職業生涯中所取得的都非常成功。然而,我想在 Google 工作,並進入大型系統中,真正地去理解計算機系統、算法效率、數據結構性能、低級別編程語言及其工作原理。可一項都不瞭解的我,怎麼會被 Google 所應聘呢?
當我創建該項目時,我從一個堆棧到一個堆都不瞭解。那時的我,完全不瞭解 Big-O 、樹,或如何去遍歷一個圖。如果非要我去編寫一個排序算法的話,我只能說我所寫的肯定是很糟糕。一直以來,我所用的任何數據結構都是內建於編程語言當中。至於它們在背後是如何運作,對此我一概不清楚。此外,以前的我並不需要對內存進行管理,最多就只是在一個正在執行的進程拋出了“內存不足”的錯誤後,採取一些權變措施。而在我的編程生活中,也甚少使用到多維數組,可關聯數組卻成千上萬。而且,從一開始到現在,我都還未曾自己實現過數據結構。
就是這樣的我,在經過該學習計劃後,已然對被 Google 所僱傭充滿信心。這是一個漫長的計劃,以至於花費了我數月的時間。若您早已熟悉大部分的知識,那麼也許能節省大量的時間。
如何使用它
下面所有的東西都只是一個概述。因此,你需要由上而下逐一地去處理它。
在學習過程中,我是使用 GitHub 特殊的語法特性 markdown flavor 去檢查計劃的進展,包括使用任務列表。
- [x] 創建一個新的分支,以使得你可以像這樣去檢查計劃的進展。直接往方括號中填寫一個字符 x 即可:[x]
更多關於 Github-flavored markdown 的詳情
擁有一名 Googler 的心態
把一個(或兩個)印有“future Googler”的圖案打印出來,並用你誓要成功的眼神盯着它。
我得到了工作嗎?
我還沒去應聘。
因爲我離完成學習(完成該瘋狂的計劃列表)還需要數天的時間,並打算在下週開始用一整天的時間,以編程的方式去解決問題。當然,這將會持續數週的時間。然後,我才通過使用在二月份所得到的一個介紹資格,去正式應聘 Google(沒錯,是二月份時就得到的)。
感謝 JP 的這次介紹。
跟隨着我
目前我仍在該計劃的執行過程中,如果你想跟隨我腳步去學習的話,可以登進我在 GoogleyAsHeck.com 上所寫的博客。
下面是我的聯繫方式:
- Twitter: @googleyasheck
- Twitter: @StartupNextDoor
- Google+: +Googleyasheck
- LinkedIn: johnawasham
不要自以爲自己不夠聰明
- Google 的工程師都是才智過人的。但是,就算是工作在 Google 的他們,仍然會因爲自己不夠聰明而感到一種不安。
- 天才程序員的神話
關於 Google
- [ ] 面向學生 —— Google 的職業生涯:技術開發指導
- [ ] Google 檢索的原理:
- [ ] 系列文章:
- [ ] 書籍:Google 公司是如何運作的
- [ ] 由 Google 通告所製作 —— 2016年10月(視頻)
相關視頻資源
部分視頻只能通過在 Coursera、Edx 或 Lynda.com class 上註冊登錄才能觀看。這些視頻被稱爲網絡公開課程(MOOC)。即便是免費觀看,部分課程可能會由於不在時間段內而無法獲取。因此,你需要多等待幾個月。
很感謝您能幫我把網絡公開課程的視頻鏈接轉換成公開的視頻源,以代替那些在線課程的視頻。此外,一些大學的講座視頻也是我所青睞的。
面試過程 & 通用的面試準備
[ ] 視頻:
[ ] 文章:
- [ ] 三步成爲 Googler
- [ ] 得到在 Google 的工作機會
- 所有他所提及的事情都列在了下面
- [ ] (早已過期) 如何得到 Google 的一份工作,面試題,應聘過程
- [ ] 手機設備屏幕的問題
[ ] 附加的(雖然 Google 不建議,但我還是添加在此):
- [ ] ABC:永遠都要去編程(Always Be Coding)
- [ ] 四步成爲 Google 裏一名沒有學位的員工
- [ ] 共享白板(Whiteboarding)
- [ ] Google 是如何看待應聘、管理和公司文化
- [ ] 程序開發面試中有效的白板(Whiteboarding)
- [ ] 震撼開發類面試 第一集:
- [ ] 如何在世界四強企業中獲得一份工作:
- [ ] 面試 Google 失敗
爲你的面試選擇一種語言
在這,我就以下話題寫一篇短文 —— 重點:爲在 Google 的面試選擇一種語言
在大多數公司的面試當中,你可以在編程這一環節,使用一種自己用起來較爲舒適的語言去完成編程。但在 Google,你只有三種固定的選擇:
- C++
- Java
- Python
有時你也可以使用下面兩種,但需要事先查閱說明。因爲,說明中會有警告:
- JavaScript
- Ruby
你需要對你所選擇的語言感到非常舒適且足夠了解。
更多關於語言選擇的閱讀:
- http://www.byte-by-byte.com/choose-the-right-language-for-your-coding-interview/
- http://blog.codingforinterviews.com/best-programming-language-jobs/
- https://www.quora.com/What-is-the-best-language-to-program-in-for-an-in-person-Google-interview
由於,我正在學習C、C++ 和 Python。因此,在下面你會看到部分關於它們的學習資料。相關書籍請看文章的底部。
在你開始之前
該列表已經持續更新了很長的一段時間,所以,我們的確很容易會對其失去控制。
這裏列出了一些我所犯過的錯誤,希望您不要重滔覆轍。
1. 你不可能把所有的東西都記住
就算我查看了數小時的視頻,並記錄了大量的筆記。幾個月後的我,仍然會忘卻其中大部分的東西。所以,我翻閱了我的筆記,並將可回顧的東西製作成抽認卡(flashcard)(請往下看)
2. 使用抽認卡
爲了解決善忘的問題,我製作了一些關於抽認卡的頁面,用於添加兩種抽認卡:正常的及帶有代碼的。每種卡都會有不同的格式設計。
而且,我還以移動設備爲先去設計這些網頁,以使得在任何地方的我,都能通過我的手機及平板去回顧知識。
你也可以免費製作屬於你自己的抽認卡網站:
- 抽認卡頁面的代碼倉庫
- 我的抽認卡數據庫:有一點需要記住的是,我做事有點過頭,以至於把卡片都覆蓋到所有的東西上。從彙編語言和 Python 的細枝末節,乃至到機器學習和統計都被覆蓋到卡片上。而這種做法,對於 Google 的要求來說,卻是多餘。
在抽認卡上做筆記: 若你第一次發現你知道問題的答案時,先不要急着把其標註成“已懂”。你需要做的,是去查看一下是否有同樣的抽認卡,並在你真正懂得如何解決問題之前,多問自己幾次。重複地問答可幫助您深刻記住該知識點。
3. 回顧,回顧,回顧
我留有一組 ASCII 碼錶、OSI 堆棧、Big-O 記號及更多的小抄紙,以便在空餘的時候可以學習。
每編程半個小時就要休息一下,並去回顧你的抽認卡。
4. 專注
在學習的過程中,往往會有許多令人分心的事佔據着我們寶貴的時間。因此,專注和集中注意力是非常困難的。
你所看不到的
由於,這個巨大的列表一開始是作爲我個人從 Google 面試指導筆記所形成的一個事件處理列表。因此,有一些我熟悉且普遍的技術在此都未被談及到:
- SQL
- Javascript
- HTML、CSS 和其他前端技術
日常計劃
部分問題可能會花費一天的時間去學習,而部分則會花費多天。當然,有些學習並不需要我們懂得如何實現。
因此,每一天我都會在下面所列出的列表中選擇一項,並查看相關的視頻。然後,使用以下的一種語言去實現:
C —— 使用結構體和函數,該函數會接受一個結構體指針 * 及其他數據作爲參數。
C++ —— 不使用內建的數據類型。
C++ —— 使用內建的數據類型,如使用 STL 的 std::list 來作爲鏈表。
Python —— 使用內建的數據類型(爲了持續練習 Python),並編寫一些測試去保證自己代碼的正確性。有時,只需要使用斷言函數 assert() 即可。
此外,你也可以使用 Java 或其他語言。以上只是我的個人偏好而已。
爲何要在這些語言上分別實現一次?
因爲可以練習,練習,練習,直至我厭倦它,並完美地實現出來。(若有部分邊緣條件沒想到時,我會用書寫的形式記錄下來並去記憶)
因爲可以在純原生的條件下工作(不需垃圾回收機制的幫助下,分配/釋放內存(除了 Python))
因爲可以利用上內建的數據類型,以使得我擁有在現實中使用內建工具的經驗(在生產環境中,我不會去實現自己的鏈表)
就算我沒有時間去每一項都這麼做,但我也會盡我所能的。
在這裏,你可以查看到我的代碼:
- C
- C++
- Python
你不需要記住每一個算法的內部原理。
在一個白板上寫代碼,而不要直接在計算機上編寫。在測試完部分簡單的輸入後,到計算機上再測試一遍。
必備知識
[ ] 計算機是如何處理一段程序:
- [ ] CPU 是如何執行代碼(視頻)
- [ ] 機器碼指令(視頻)
[ ] 編譯器
- [ ] 編譯器是如何在 ~1 分鐘內工作(視頻)
- [ ] Harvard CS50 —— 編譯器(視頻)
- [ ] C++(視頻)
- [ ] 掌握編譯器的優化(C++)(視頻)
[ ] 浮點數是如何存儲的:
- [ ] 簡單的 8-bit:浮點數的表達形式 —— 1(視頻 —— 在計算上有一個錯誤 —— 詳情請查看視頻的介紹)
- [ ] 32 bit:IEEE754 32-bit 浮點二進制(視頻)
算法複雜度 / Big-O / 漸進分析法
- 並不需要實現
- [ ] Harvard CS50 —— 漸進表示(視頻)
- [ ] Big O 記號(通用快速教程)(視頻)
- [ ] Big O 記號(以及 Omega 和 Theta)—— 最佳數學解釋(視頻)
- [ ] Skiena 算法:
- [ ] 對於算法複雜度分析的一次詳細介紹
- [ ] 增長階數(Orders of Growth)(視頻)
- [ ] 漸進性(Asymptotics)(視頻)
- [ ] UC Berkeley Big O(視頻)
- [ ] UC Berkeley Big Omega(視頻)
- [ ] 平攤分析法(Amortized Analysis)(視頻)
- [ ] 舉證“Big O”(視頻)
- [ ] 高級編程(包括遞歸關係和主定理):
[ ] 速查表(Cheat sheet)
如果部分課程過於學術性,你可直接跳到文章底部,去查看離散數學的視頻以獲取相關背景知識。
數據結構
數組(Arrays)
- 實現一個可自動調整大小的動態數組。
- [ ] 介紹:
- [ ] 實現一個動態數組(可自動調整大小的可變數組):
- [ ] 練習使用數組和指針去編碼,並且指針是通過計算去跳轉而不是使用索引
- [ ] 通過分配內存來新建一個原生數據型數組
- 可以使用 int 類型的數組,但不能使用其語法特性
- 從大小爲16或更大的數(使用2的倍數 —— 16、32、64、128)開始編寫
- [ ] size() —— 數組元素的個數
- [ ] capacity() —— 可容納元素的個數
- [ ] is_empty()
- [ ] at(index) —— 返回對應索引的元素,且若索引越界則憤然報錯
- [ ] push(item)
- [ ] insert(index, item) —— 在指定索引中插入元素,並把後面的元素依次後移
- [ ] prepend(item) —— 可以使用上面的 insert 函數,傳參 index 爲 0
- [ ] pop() —— 刪除在數組末端的元素,並返回其值
- [ ] delete(index) —— 刪除指定索引的元素,並把後面的元素依次前移
- [ ] remove(item) —— 刪除指定值的元素,並返回其索引(即使有多個元素)
- [ ] find(item) —— 尋找指定值的元素並返回其中第一個出現的元素其索引,若未找到則返回 -1
- [ ] resize(new_capacity) // 私有函數
- 若數組的大小到達其容積,則變大一倍
- 獲取元素後,若數組大小爲其容積的1/4,則縮小一半
- [ ] 時間複雜度
- 在數組末端增加/刪除、定位、更新元素,只允許佔 O(1) 的時間複雜度(平攤(amortized)去分配內存以獲取更多空間)
- 在數組任何地方插入/移除元素,只允許 O(n) 的時間複雜度
- [ ] 空間複雜度
- 因爲在內存中分配的空間鄰近,所以有助於提高性能
- 空間需求 = (大於或等於 n 的數組容積)* 元素的大小。即便空間需求爲 2n,其空間複雜度仍然是 O(n)
鏈表(Linked Lists)
- [ ] 介紹:
- [ ] 單向鏈表(視頻)
- [ ] CS 61B —— 鏈表(視頻)
- [ ] C 代碼(視頻)
- 並非看完整個視頻,只需要看關於節點結果和內存分配那一部分即可
- [ ] 鏈表 vs 數組:
- [ ] 爲什麼你需要避免使用鏈表(視頻)
- [ ] 的確:你需要關於“指向指針的指針”的相關知識:(因爲當你傳遞一個指針到一個函數時,該函數可能會改變指針所指向的地址)該頁只是爲了讓你瞭解“指向指針的指針”這一概念。但我並不推薦這種鏈式遍歷的風格。因爲,這種風格的代碼,其可讀性和可維護性太低。
- [ ] 實現(我實現了使用尾指針以及沒有使用尾指針這兩種情況):
- [ ] size() —— 返回鏈表中數據元素的個數
- [ ] empty() —— 若鏈表爲空則返回一個布爾值 true
- [ ] value_at(index) —— 返回第 n 個元素的值(從0開始計算)
- [ ] push_front(value) —— 添加元素到鏈表的首部
- [ ] pop_front() —— 刪除首部元素並返回其值
- [ ] push_back(value) —— 添加元素到鏈表的尾部
- [ ] pop_back() —— 刪除尾部元素並返回其值
- [ ] front() —— 返回首部元素的值
- [ ] back() —— 返回尾部元素的值
- [ ] insert(index, value) —— 插入值到指定的索引,並把當前索引的元素指向到新的元素
- [ ] erase(index) —— 刪除指定索引的節點
- [ ] value_n_from_end(n) —— 返回倒數第 n 個節點的值
- [ ] reverse() —— 逆序鏈表
- [ ] remove_value(value) —— 刪除鏈表中指定值的第一個元素
- [ ] 雙向鏈表
- 介紹(視頻)
- 並不需要實現
- [ ] 介紹:
堆棧(Stack)
- [ ] 堆棧(視頻)
- [ ] 使用堆棧 —— 後進先出(視頻)
- [ ] 可以不實現,因爲使用數組來實現並不重要
隊列(Queue)
- [ ] 使用隊列 —— 先進先出(視頻)
- [ ] 隊列(視頻)
- [ ] 原型隊列/先進先出(FIFO)
- [ ] 優先級隊列(視頻)
- [ ] 使用含有尾部指針的鏈表來實現:
- enqueue(value) —— 在尾部添加值
- dequeue() —— 刪除最早添加的元素並返回其值(首部元素)
- empty()
- [ ] 使用固定大小的數組實現:
- enqueue(value) —— 在可容的情況下添加元素到尾部
- dequeue() —— 刪除最早添加的元素並返回其值
- empty()
- full()
- [ ] 花銷:
- 在糟糕的實現情況下,使用鏈表所實現的隊列,其入列和出列的時間複雜度將會是 O(n)。因爲,你需要找到下一個元素,以致循環整個隊列
- enqueue:O(1)(平攤(amortized)、鏈表和數組 [探測(probing)])
- dequeue:O(1)(鏈表和數組)
- empty:O(1)(鏈表和數組)
哈希表(Hash table)
[ ] 視頻:
[ ] 在線課程:
- [ ] 哈希函數的掌握(視頻)
- [ ] 使用哈希表(視頻)
- [ ] 哈希表的支持(視頻)
- [ ] 哈希表的語言支持(視頻)
- [ ] 基本哈希表(視頻)
- [ ] 數據結構(視頻)
- [ ] 電話薄問題(Phone Book Problem)(視頻)
- [ ] 分佈式哈希表:
[ ] 使用線性探測的數組去實現
- hash(k, m) —— m 是哈希表的大小
- add(key, value) —— 如果 key 已存在則更新值
- exists(key)
- get(key)
- remove(key)
更多的知識
二分查找(Binary search)
按位運算(Bitwise operations)
- [ ] Bits 速查表
- 你需要知道大量2的冪數值(從2^1 到 2^16 及 2^32)
- [ ] 好好理解位操作符的含義:&、|、^、~、>>、<<
- [ ] 字碼(words)
- [ ] 好的介紹:
位操作(視頻) - [ ] C 語言編程教程 2-10:按位運算(視頻)
- [ ] 位操作
- [ ] 按位運算
- [ ] Bithacks
- [ ] 位元撫弄者(The Bit Twiddler)
- [ ] 交互式位元撫弄者(The Bit Twiddler Interactive)
- [ ] 一補數和補碼
- [ ] 計算置位(Set Bits)
- [ ] 四捨五入2的冪數:
- [ ] 交換值:
- [ ] 絕對值:
- [ ] Bits 速查表
樹(Trees)
樹 —— 筆記 & 背景
- [ ] 系列:基本樹(視頻)
- [ ] 系列:樹(視頻)
- 基本的樹形結構
- 遍歷
- 操作算法
- BFS(廣度優先檢索,breadth-first search)
- MIT(視頻)
- 層序遍歷(使用隊列的 BFS 算法)
- 時間複雜度: O(n)
- 空間複雜度:
- 最好情況: O(1)
- 最壞情況:O(n/2)=O(n)
- DFS(深度優先檢索,depth-first search)
- MIT(視頻)
- 筆記:
- 時間複雜度:O(n)
- 空間複雜度:
- 最好情況:O(log n) - 樹的平均高度
- 最壞情況:O(n)
- 中序遍歷(DFS:左、節點本身、右)
- 後序遍歷(DFS:左、右、節點本身)
- 先序遍歷(DFS:節點本身、左、右)
二叉查找樹(Binary search trees):BSTs
- [ ] 二叉查找樹概覽(視頻)
- [ ] 系列(視頻)
- 從符號表開始到 BST 程序
- [ ] 介紹(視頻)
- [ ] MIT(視頻)
- C/C++:
- [ ] 二叉查找樹 —— 在 C/C++ 中實現(視頻)
- [ ] BST 的實現 —— 在堆棧和堆中的內存分配(視頻)
- [ ] 在二叉查找樹中找到最小和最大的元素(視頻)
- [ ] 尋找二叉樹的高度(視頻)
- [ ] 二叉樹的遍歷 —— 廣度優先和深度優先策略(視頻)
- [ ] 二叉樹:層序遍歷(視頻)
- [ ] 二叉樹的遍歷:先序、中序、後序(視頻)
- [ ] 判斷一棵二叉樹是否爲二叉查找樹(視頻)
- [ ] 從二叉查找樹中刪除一個節點(視頻)
- [ ] 二叉查找樹中序遍歷的後繼者(視頻)
- [ ] 實現:
- [ ] insert // 往樹上插值
- [ ] get_node_count // 查找樹上的節點數
- [ ] print_values // 從小到大打印樹中節點的值
- [ ] delete_tree
- [ ] is_in_tree // 如果值存在於樹中則返回 true
- [ ] get_height // 返回節點所在的高度(如果只有一個節點,那麼高度則爲1)
- [ ] get_min // 返回樹上的最小值
- [ ] get_max // 返回樹上的最大值
- [ ] is_binary_search_tree
- [ ] delete_value
- [ ] get_successor // 返回給定值的後繼者,若沒有則返回-1
堆(Heap) / 優先級隊列(Priority Queue) / 二叉堆(Binary Heap)
- 可視化是一棵樹,但通常是以線性的形式存儲(數組、鏈表)
- [ ] 堆
- [ ] 介紹(視頻)
- [ ] 無知的實現(視頻)
- [ ] 二叉樹(視頻)
- [ ] 關於樹高的討論(視頻)
- [ ] 基本操作(視頻)
- [ ] 完全二叉樹(視頻)
- [ ] 僞代碼(視頻)
- [ ] 堆排序 —— 跳到起點(視頻)
- [ ] 堆排序(視頻)
- [ ] 構建一個堆(視頻)
- [ ] MIT:堆與堆排序(視頻)
- [ ] CS 61B Lecture 24:優先級隊列(視頻)
- [ ] 構建線性時間複雜度的堆(大頂堆)
- [ ] 實現一個大頂堆:
- [ ] insert
- [ ] sift_up —— 用於插入元素
- [ ] get_max —— 返回最大值但不移除元素
- [ ] get_size() —— 返回存儲的元素數量
- [ ] is_empty() —— 若堆爲空則返回 true
- [ ] extract_max —— 返回最大值並移除
- [ ] sift_down —— 用於獲取最大值元素
- [ ] remove(i) —— 刪除指定索引的元素
- [ ] heapify —— 構建堆,用於堆排序
- [ ] heap_sort() —— 拿到一個未排序的數組,然後使用大頂堆進行就地排序
- 注意:若用小頂堆可節省操作,但導致空間複雜度加倍。(無法做到就地)
字典樹(Tries)
- 需要注意的是,字典樹各式各樣。有些有前綴,而有些則沒有。有些使用字符串而不使用比特位來追蹤路徑。
- 閱讀代碼,但不實現。
- [ ] 數據結構筆記及編程技術
- [ ] 短課程視頻:
- [ ] 對字典樹的介紹(視頻)
- [ ] 字典樹的性能(視頻)
- [ ] 實現一棵字典樹(視頻)
- [ ] 字典樹:一個被忽略的數據結構
- [ ] 高級編程 —— 使用字典樹
- [ ] 標準教程(現實中的用例)(視頻)
- [ ] MIT,高階數據結構,使用字符串追蹤路徑(可事半功倍)
平衡查找樹(Balanced search trees)
- 掌握至少一種平衡查找樹(並懂得如何實現):
- “在各種平衡查找樹當中,AVL 樹和2-3樹已經成爲了過去,而紅黑樹(red-black trees)看似變得越來越受人青睞。這種令人特別感興趣的數據結構,亦稱伸展樹(splay tree)。它可以自我管理,且會使用輪換來移除任何訪問過根節點的 key。” —— Skiena
- 因此,在各種各樣的平衡查找樹當中,我選擇了伸展樹來實現。雖然,通過我的閱讀,我發現在 Google 的面試中並不會被要求實現一棵平衡查找樹。但是,爲了勝人一籌,我們還是應該看看如何去實現。在閱讀了大量關於紅黑樹的代碼後,我才發現伸展樹的實現確實會使得各方面更爲高效。
- 伸展樹:插入、查找、刪除函數的實現,而如果你最終實現了紅黑樹,那麼請嘗試一下:
- 跳過刪除函數,直接實現搜索和插入功能
- 我希望能閱讀到更多關於 B 樹的資料,因爲它也被廣泛地應用到大型的數據庫當中。
[ ] 自平衡二叉查找樹
[ ] AVL 樹
- 實際中:我能告訴你的是,該種樹並無太多的用途,但我能看到有用的地方在哪裏:AVL 樹是另一種平衡查找樹結構。其可支持時間複雜度爲 O(log n) 的查詢、插入及刪除。它比紅黑樹嚴格意義上更爲平衡,從而導致插入和刪除更慢,但遍歷卻更快。正因如此,才彰顯其結構的魅力。只需要構建一次,就可以在不重新構造的情況下讀取,適合於實現諸如語言字典(或程序字典,如一個彙編程序或解釋程序的操作碼)。
- [ ] MIT AVL 樹 / AVL 樹的排序(視頻)
- [ ] AVL 樹(視頻)
- [ ] AVL 樹的實現(視頻)
- [ ] 分離與合併
[ ] 伸展樹
- 實際中:伸展樹一般用於緩存、內存分配者、路由器、垃圾回收者、數據壓縮、ropes(字符串的一種替代品,用於存儲長串的文本字符)、Windows NT(虛擬內存、網絡及文件系統)等的實現。
- [ ] CS 61B:伸展樹(Splay trees)(視頻)
- [ ] MIT 教程:伸展樹(Splay trees):
- 該教程會過於學術,但請觀看到最後的10分鐘以確保掌握。
- 視頻
[ ] 2-3查找樹
- 實際中:2-3樹的元素插入非常快速,但卻有着查詢慢的代價(因爲相比較 AVL 樹來說,其高度更高)。
- 你會很少用到2-3樹。這是因爲,其實現過程中涉及到不同類型的節點。因此,人們更多地會選擇紅黑樹。
- [ ] 2-3樹的直感與定義(視頻)
- [ ] 2-3樹的二元觀點
- [ ] 2-3樹(學生敘述)(視頻)
[ ] 2-3-4樹 (亦稱2-4樹)
- 實際中:對於每一棵2-4樹,都有着對應的紅黑樹來存儲同樣順序的數據元素。在2-4樹上進行插入及刪除操作等同於在紅黑樹上進行顏色翻轉及輪換。這使得2-4樹成爲一種用於掌握紅黑樹背後邏輯的重要工具。這就是爲什麼許多算法引導文章都會在介紹紅黑樹之前,先介紹2-4樹,儘管2-4樹在實際中並不經常使用。
- [ ] CS 61B Lecture 26:平衡查找樹(視頻)
- [ ] 自底向上的2-4樹(視頻)
- [ ] 自頂向下的2-4樹(視頻)
[ ] B 樹
- 有趣的是:爲啥叫 B 仍然是一個神祕。因爲 B 可代表波音(Boeing)、平衡(Balanced)或 Bayer(聯合創造者)
- 實際中:B 樹會被廣泛適用於數據庫中,而現代大多數的文件系統都會使用到這種樹(或變種)。除了運用在數據庫中,B 樹也會被用於文件系統以快速訪問一個文件的任意塊。但存在着一個基本的問題,那就是如何將文件塊 i 轉換成一個硬盤塊(或一個柱面-磁頭-扇區)上的地址。
- [ ] B 樹
- [ ] B 樹的介紹(視頻)
- [ ] B 樹的定義及其插入操作(視頻)
- [ ] B 樹的刪除操作(視頻)
- [ ] MIT 6.851 —— 內存層次模塊(Memory Hierarchy Models)(視頻)
- 覆蓋有高速緩存參數無關型(cache-oblivious)B 樹和非常有趣的數據結構
- 頭37分鐘講述的很專業,或許可以跳過(B 指塊的大小、即緩存行的大小)
[ ] 紅黑樹
- 實際中:紅黑樹提供了在最壞情況下插入操作、刪除操作和查找操作的時間保證。這些時間值的保障不僅對時間敏感型應用有用,例如實時應用,還對在其他數據結構中塊的構建非常有用,而這些數據結構都提供了最壞情況下的保障;例如,許多用於計算幾何學的數據結構都可以基於紅黑樹,而目前 Linux 系統所採用的完全公平調度器(the Completely Fair Scheduler)也使用到了該種樹。在 Java 8中,紅黑樹也被用於存儲哈希列表集合中相同的數據,而不是使用鏈表及哈希碼。
- [ ] Aduni —— 算法 —— 課程4(該鏈接直接跳到開始部分)(視頻)
- [ ] Aduni —— 算法 —— 課程5(視頻)
- [ ] 黑樹(Black Tree)
- [ ] 二分查找及紅黑樹的介紹
N 叉樹(K 叉樹、M 叉樹)
- 注意:N 或 K 指的是分支系數(即樹的最大分支數):
- 二叉樹是一種分支系數爲2的樹
- 2-3樹是一種分支系數爲3的樹
- [ ] K 叉樹
- 注意:N 或 K 指的是分支系數(即樹的最大分支數):
排序(Sorting)
[ ] 筆記:
關於堆排序,請查看前文堆的數據結構部分。堆排序很強大,不過是非穩定排序。
[ ] 冒泡排序 (video)
- [ ] 冒泡排序分析 (video)
- [ ] 插入排序 & 歸併排序 (video)
- [ ] 插入排序 (video)
- [ ] 歸併排序 (video)
- [ ] 快排 (video)
[ ] 選擇排序 (video)
[ ] 斯坦福大學關於排序算法的視頻:
[ ] Shai Simonson 視頻, Aduni.org:
[ ] Steven Skiena 關於排序的視頻:
[ ] 加州大學伯克利分校(UC Berkeley) 大學課程:
[ ] - 歸併排序:
[ ] - 快速排序:
[ ] 實現:
- [ ] 歸併:平均和最差情況的時間複雜度爲 O(n log n)。
- [ ] 快排:平均時間複雜度爲 O(n log n)。
- 選擇排序和插入排序的最壞、平均時間複雜度都是 O(n^2)。
- 關於堆排序,請查看前文堆的數據結構部分。
[ ] 有興趣的話,還有一些補充 - 但並不是必須的:
- [ ] 基數排序
- [ ] 基數排序 (video)
- [ ] 基數排序, 計數排序 (線性時間內) (video)
- [ ] 隨機算法: 矩陣相乘, 快排, Freivalds’ 算法 (video)
- [ ] 線性時間內的排序 (video)
圖(Graphs)
圖論能解決計算機科學裏的很多問題,所以這一節會比較長,像樹和排序的部分一樣。
Yegge 的筆記:
- 有 3 種基本方式在內存裏表示一個圖:
- 對象和指針
- 矩陣
- 鄰接表
- 熟悉以上每一種圖的表示法,並瞭解各自的優缺點
- 寬度優先搜索和深度優先搜索 - 知道它們的計算複雜度和設計上的權衡以及如何用代碼實現它們
- 遇到一個問題時,首先嚐試基於圖的解決方案,如果沒有再去嘗試其他的。
- 有 3 種基本方式在內存裏表示一個圖:
[ ] Skiena 教授的課程 - 很不錯的介紹:
[ ] 圖 (複習和其他):
- [ ] 6.006 單源最短路徑問題 (video)
- [ ] 6.006 Dijkstra 算法 (video)
- [ ] 6.006 Bellman-Ford 算法(video)
- [ ] 6.006 Dijkstra 效率優化 (video)
- [ ] Aduni: 圖的算法 I - 拓撲排序, 最小生成樹, Prim 算法 - 第六課 (video)
- [ ] Aduni: 圖的算法 II - 深度優先搜索, 廣度優先搜索, Kruskal 算法, 並查集數據結構 - 第七課 (video)
- [ ] Aduni: 圖的算法 III: 最短路徑 - 第八課 (video)
- [ ] Aduni: 圖的算法. IV: 幾何算法介紹 - 第九課 (video)
- [ ] CS 61B 2014 (從 58:09 開始) (video)
- [ ] CS 61B 2014: 加權圖 (video)
- [ ] 貪心算法: 最小生成樹 (video)
- [ ] 圖的算法之強連通分量 Kosaraju 算法 (video)
完整的 Coursera 課程:
- [ ] 圖的算法 (video)
Yegge: 如果有機會,可以試試研究更酷炫的算法:
- [ ] Dijkstra 算法 - 上文 - 6.006
- [ ] A* 算法
- [ ] A* 算法
- [ ] A* 尋路教程 (video)
- [ ] A* 尋路 (E01: 算法解釋) (video)
我會實現:
- [ ] DFS 鄰接表 (遞歸)
- [ ] DFS 鄰接表 (棧迭代)
- [ ] DFS 鄰接矩陣 (遞歸)
- [ ] DFS 鄰接矩陣 (棧迭代)
- [ ] BFS 鄰接表
- [ ] BFS 鄰接矩陣
- [ ] 單源最短路徑問題 (Dijkstra)
- [ ] 最小生成樹
- 基於 DFS 的算法 (根據上文 Aduni 的視頻):
- [ ] 檢查環 (我們會先檢查是否有環存在以便做拓撲排序)
- [ ] 拓撲排序
- [ ] 計算圖中的連通分支
- [ ] 列出強連通分量
- [ ] 檢查雙向圖
可以從 Skiena 的書(參考下面的書推薦小節)和麪試書籍中學習更多關於圖的實踐。
更多知識
遞歸(Recursion)
- [ ] Stanford 大學關於遞歸 & 回溯的課程:
- 什麼時候適合使用
- 尾遞歸會更好麼?
- [ ] 什麼是尾遞歸以及爲什麼它如此糟糕?
- [ ] 尾遞歸 (video)
- [ ] Stanford 大學關於遞歸 & 回溯的課程:
動態規劃(Dynamic Programming)
- This subject can be pretty difficult, as each DP soluble problem must be defined as a recursion relation, and coming up with it can be tricky.
- 這一部分會有點困難,每個可以用動態規劃解決的問題都必須先定義出遞推關係,要推導出來可能會有點棘手。
我建議先閱讀和學習足夠多的動態規劃的例子,以便對解決 DP 問題的一般模式有個紮實的理解。
[ ] 視頻:
- Skiena 的視頻可能會有點難跟上,有時候他用白板寫的字會比較小,難看清楚。
- [ ] Skiena: CSE373 2012 - 課程 19 - 動態規劃介紹 (video)
- [ ] Skiena: CSE373 2012 - 課程 20 - 編輯距離 (video)
- [ ] Skiena: CSE373 2012 - 課程 21 - 動態規劃舉例 (video)
- [ ] Skiena: CSE373 2012 - 課程 22 - 動態規劃應用 (video)
- [ ] Simonson: 動態規劃 0 (starts at 59:18) (video)
- [ ] Simonson: 動態規劃 I - 課程 11 (video)
- [ ] Simonson: 動態規劃 II - 課程 12 (video)
- [ ] 單獨的 DP 問題 (每一個視頻都很短):
動態規劃 (video)
- [ ] Yale 課程筆記:
- [ ] 動態規劃
- [ ] Coursera 課程:
- [ ] RNA 二級結構問題 (video)
- [ ] 動態規劃算法 (video)
- [ ] DP 算法描述 (video)
- [ ] DP 算法的運行時間 (video)
- [ ] DP vs 遞歸實現 (video)
- [ ] 全局成對序列排列 (video)
- [ ] 本地成對序列排列 (video)
組合(Combinatorics) (n 中選 k 個) & 概率(Probability)
- [ ] 數據技巧: 如何找出階乘、排列和組合(選擇) (video)
- [ ] 來點學校的東西: 概率 (video)
- [ ] 來點學校的東西: 概率和馬爾可夫鏈 (video)
- [ ] 可汗學院:
- 課程設置:
- [ ] 概率理論基礎
- 視頻 - 41 (每一個都短小精悍):
- [ ] 概率解釋 (video)
- 課程設置:
NP, NP-完全和近似算法
- 知道最經典的一些 NP 完全問題,比如旅行商問題和揹包問題,
而且能在面試官試圖忽悠你的時候識別出他們。 - 知道 NP 完全是什麼意思.
- [ ] 計算複雜度 (video)
- [ ] Simonson:
- [ ] Skiena:
- [ ] 複雜度: P, NP, NP-完全性, 規約 (video)
- [ ] 複雜度: 近視算法 Algorithms (video)
- [ ] 複雜度: 固定參數算法 (video)
- Peter Norvik 討論旅行商問題的近似最優解:
- 《算法導論》的第 1048 - 1140 頁。
- 知道最經典的一些 NP 完全問題,比如旅行商問題和揹包問題,
緩存(Cache)
- [ ] LRU 緩存:
- [ ] CPU 緩存:
- [ ] LRU 緩存:
進程(Processe)和線程(Thread)
- [ ] 計算機科學 162 - 操作系統 (25 個視頻):
- 視頻 1-11 是關於進程和線程
- 操作系統和系統編程 (video)
- 進程和線程的區別是什麼?
- 涵蓋了:
- 進程、線程、協程
- 進程和線程的區別
- 進程
- 線程
- 鎖
- 互斥
- 信號量
- 監控
- 他們是如何工作的
- 死鎖
- 活鎖
- CPU 活動, 中斷, 上下文切換
- 現代多核處理器的併發式結構
- 進程資源需要(內存:代碼、靜態存儲器、棧、堆、文件描述符、I/O)
- 線程資源需要(在同一個進程內和其他線程共享以上的資源,但是每個線程都有獨立的程序計數器、棧計數器、寄存器和棧)
- Fork 操作是真正的寫時複製(只讀),直到新的進程寫到內存中,纔會生成一份新的拷貝。
- 上下文切換
- 操作系統和底層硬件是如何初始化上下文切換的。
- 進程、線程、協程
- [ ] C++ 的線程 (系列 - 10 個視頻)
- [ ] Python 的協程 (視頻):
系統設計以及可伸縮性,要把軟硬件的伸縮性設計的足夠好有很多的東西要考慮,所以這是個包含非常多內容和資源的大主題。需要花費相當多的時間在這個主題上。
- [ ] 計算機科學 162 - 操作系統 (25 個視頻):
系統設計、可伸縮性、數據處理
- Yegge 的注意事項:
- 伸縮性
- 把大數據集提取爲單一值
- 大數據集轉換
- 處理大量的數據集
- 系統
- 特徵集
- 接口
- 類層次結構
- 在特定的約束下設計系統
- 輕量和健壯性
- 權衡和折衷
- 性能分析和優化
- 伸縮性
- [ ] 從這裏開始: HiredInTech:系統設計
- [ ] 該如何爲技術面試裏設計方面的問題做準備?
- [ ] 在系統設計面試前必須知道的 8 件事
- [ ] 算法設計
- [ ] 數據庫範式 - 1NF, 2NF, 3NF and 4NF (video)
- [ ] 系統設計面試 - 這一部分有很多的資源,瀏覽一下我放在下面的文章和例子。
- [ ] 如何在系統設計面試中脫穎而出
- [ ] 每個人都該知道的一些數字
- [ ] 上下文切換操作會耗費多少時間?
- [ ] 跨數據中心的事務 (video)
- [ ] 簡明 CAP 理論介紹
- [ ] Paxos 一致性算法:
- [ ] 一致性哈希
- [ ] NoSQL 模式
- [ ] OOSE: UML 2.0 系列 (video)
- [ ] OOSE: 使用 UML 和 Java 開發軟件 (21 videos):
- 如果你對 OO 都深刻的理解和實踐,可以跳過這部分。
- OOSE: 使用 UML 和 Java 開發軟件
- [ ] 面向對象編程的 SOLID 原則:
- [ ] Bob Martin 面向對象的 SOLID 原則和敏捷設計 (video)
- [ ] C# SOLID 設計模式 (video)
- [ ] SOLID 原則 (video)
- [ ] S - 單一職責原則 | 每個對象的單一職責
- [ ] O - 開閉原則 | 生產環境裏的對象應該爲擴展做準備而不是爲更改
- [ ] L - 里氏代換原則 | 基類和繼承類遵循 ‘IS A’ 原則
- [ ] I - 接口隔離原則 | 客戶端被迫實現用不到的接口
- [ ] D -依賴反轉原則 | 減少對象裏的依賴。
- [ ] 可伸縮性:
- [ ] 很棒的概述 (video)
- [ ] 簡短系列:
- [ ] 可伸縮的 Web 架構和分佈式系統
- [ ] 錯誤的分佈式系統解釋
- [ ] 實用編程技術
- [ ] Jeff Dean - 在 Goolge 構建軟件系統 (video)
- [ ] 可伸縮系統架構設計介紹
- [ ] 使用 App Engine 和雲存儲擴展面向全球用戶的手機遊戲架構實踐(video)
- [ ] How Google Does Planet-Scale Engineering for Planet-Scale Infra (video)
- [ ] 算法的重要性
- [ ] 分片
- [ ] Facebook 系統規模擴展實踐 (2009)
- [ ] Facebook 系統規模擴展實踐 (2012), “爲 10 億用戶構建” (video)
- [ ] Long Game 工程實踐 - Astrid Atkinson Keynote(video)
- [ ] 30 分鐘看完 YouTuBe 7 年系統擴展經驗
- [ ] PayPal 如何用 8 臺虛擬機扛住 10 億日交易量系統
- [ ] 如何對大數據集去重
- [ ] Etsy 的擴展和工程文化探究 Jon Cowie (video)
- [ ] 是什麼造就了 Amazon 自己的微服務架構
- [ ] 壓縮還是不壓縮,是 Uber 面臨的問題
- [ ] 異步 I/O Tarantool 隊列
- [ ] 什麼時候應該用近視查詢處理?
- [ ] Google 從單數據中心到故障轉移, 到本地多宿主架構的演變
- [ ] Spanner
- [ ] Egnyte: 構建和擴展 PB 級分佈式系統架構的經驗教訓
- [ ] 機器學習驅動的編程: 新世界的新編程方式
- [ ] 日服務數百萬請求的圖像優化技術
- [ ] Patreon 架構
- [ ] Tinder: 推薦引擎是如何決定下一個你將會看到誰的?
- [ ] 現代緩存設計
- [ ] Facebook 實時視頻流擴展
- [ ] 在 Amazon AWS 上把服務擴展到 1100 萬量級的新手教程
- [ ] 對延時敏感的應用是否應該使用 Docker?
- [ ] AMP(Accelerated Mobile Pages)的存在是對 Google 的威脅麼?
- [ ] 360 度解讀 Netflix 技術棧
- [ ] 延遲無處不在 - 如何搞定它?
- [ ] 無服務器架構
- [ ] 是什麼驅動着 Instagram: 上百個實例、幾十種技術
- [ ] Cinchcast 架構 - 每天處理 1500 小時的音頻
- [ ] Justin.Tv 實時視頻播放架構
- [ ] Playfish’s 社交遊戲架構 - 每月五千萬用戶增長
- [ ] 貓途鷹架構 - 40 萬訪客, 200 萬動態頁面訪問, 30TB 數據
- [ ] PlentyOfFish 架構
- [ ] Salesforce 架構 - 如何扛住 13 億日交易量
- [ ] ESPN’s 架構擴展
- [ ] 下面 『消息、序列化和消息系統』部分的內容會提到什麼樣的技術能把各種服務整合到一起
- [ ] Twitter:
- 更多內容可以查看視頻部分的『大規模數據挖掘』視頻系列。
- [ ] 系統設計問題練習:下面有一些指導原則,每一個都有相關文檔以及在現實中該如何處理。
- 複習: HiredInTech 的系統設計
- cheat sheet
- 流程:
- 理解問題和範圍:
- 在面試官的幫助下定義用例
- 提出附加功能的建議
- 去掉面試官認定範圍以外的內容
- 假定高可用是必須的,而且要作爲一個用例
- 考慮約束:
- 問一下每月請求量
- 問一下每秒請求量 (他們可能會主動提到或者讓你算一下)
- 評估讀寫所佔的百分比
- 評估的時候牢記 2/8 原則
- 每秒寫多少數據
- 總的數據存儲量要考慮超過 5 年的情況
- 每秒讀多少數據
- 抽象設計:
- 分層 (服務, 數據, 緩存)
- 基礎設施: 負載均衡, 消息
- 粗略的概括任何驅動整個服務的關鍵算法
- 考慮瓶頸並指出解決方案
- 理解問題和範圍:
- 練習:
- Yegge 的注意事項:
論文
- 有 Google 的論文和一些知名的論文.
- 你很可能實在沒時間一篇篇完整的讀完他們。我建議可以有選擇的讀其中一些論文裏的核心部分。
- [ ] 1978: 通信順序處理
- [ ] 2003: The Google 文件系統
- 2012 年被 Colossus 取代了
- [ ] 2004: MapReduce: Simplified Data Processing on Large Clusters
- 大多被雲數據流取代了?
- [ ] 2007: 每個程序員都應該知道的內存知識 (非常長,作者建議跳過某些章節來閱讀)
- [ ] 2012: Google 的 Colossus
- 沒有論文
- [ ] 2012: AddressSanitizer: 快速的內存訪問檢查器:
- [ ] 2013: Spanner: Google 的分佈式數據庫:
- [ ] 2014: Machine Learning: The High-Interest Credit Card of Technical Debt
- [ ] 2015: Continuous Pipelines at Google
- [ ] 2015: 大規模高可用: 構建 Google Ads 的數據基礎設施
- [ ] 2015: TensorFlow: 異構分佈式系統上的大規模機器學習
- [ ] 2015: 開發者應該如何搜索代碼:用例學習
- [ ] 2016: Borg, Omega, and Kubernetes
測試
- 涵蓋了:
- 單元測試是如何工作的
- 什麼是模擬對象
- 什麼是集成測試
- 什麼是依賴注入
- [ ] James Bach 講敏捷軟件測試 (video)
- [ ] James Bach 軟件測試公開課 (video)
- [ ] Steve Freeman - 測試驅動的開發 (video)
- [ ] 測試驅動的開發已死。測試不朽。
- [ ] 測試驅動的開發已死? (video)
- [ ] 視頻系列 (152 個) - 並不都是必須 (video)
- [ ] Python:測試驅動的 Web 開發
- [ ] 依賴注入:
- [ ] 如何編寫測試
- 涵蓋了:
調度
- 在操作系統中是如何運作的
- 在操作系統部分的視頻裏有很多資料
實現系統例程
- 理解你使用的系統 API 底層有什麼
- 你能自己實現它們麼?
字符串搜索和操作
- [ ] 文本的搜索模式 (video)
- [ ] Rabin-Karp (videos):
- [ ] Knuth-Morris-Pratt (KMP) 算法:
- [ ] Boyer–Moore 字符串搜索算法
- [ ] Coursera: 字符串的算法
終面
這一部分有一些短視頻,你可以快速的觀看和複習大多數重要概念。
這對經常性的鞏固很有幫助。
綜述:
排序:
書籍
Google Coaching 裏提到的
閱讀並做練習:
[ ] 算法設計手冊 (Skiena)
- 書 (Kindle 上可以租到):
- Half.com 是一個資源豐富且性價比很高的在線書店.
- 答案:
- 勘誤表
read and do exercises from the books below. Then move to coding challenges (further down below)
一旦你理解了每日計劃裏的所有內容,就去讀上面所列的書並完成練習,然後開始讀下面所列的書並做練習,之後就可以開始實戰寫代碼了(本文再往後的部分)- 書 (Kindle 上可以租到):
首先閱讀:
- [ ] Programming Interviews Exposed: Secrets to Landing Your Next Job, 2nd Edition
然後閱讀 (這本獲得了很多推薦, 但是不在 Google coaching 的文檔裏):
- [ ] Cracking the Coding Interview, 6th Edition
- 如果你看到有人在看 “The Google Resume”, 實際上它和 “Cracking the Coding Interview” 是同一個作者寫的,而且後者是升級版。
附加書單
這些沒有被 Google 推薦閱讀,不過我因爲需要這些背景知識所以也把它們列在了這裏。
[ ] C Programming Language, Vol 2
[ ] C++ Primer Plus, 6th Edition
如果你有時間
[ ] Elements of Programming Interviews
- 如果你希望在面試裏用 C++ 寫代碼,這本書的代碼全都是 C++ 寫的
- 通常情況下能找到解決方案的好書.
編碼練習和挑戰
一旦你學會了理論基礎,就應該把它們拿出來練練。
儘量堅持每天做編碼練習,越多越好。
編程問題預備:
- [ ] 不錯的介紹 (摘自 System Design 章節): 算法設計:
- [ ] 如何找到解決方案
- [ ] 如何剖析 Topcoder 題目描述
- [ ] Topcoders 裏用到的數學
[ ] 動態規劃 – 從入門到精通
編碼練習平臺:
當你臨近面試時
- [ ] 搞定代碼面試 (videos):
你的簡歷
- 10 條小貼士讓你寫出一份還算不錯的簡歷
- 這是搞定面試的第一個關鍵步驟
當面試來臨的時候
隨着下面列舉的問題思考下你可能會遇到的 20 個面試問題
每個問題準備 2-3 種回答
準備點故事,不要只是擺一些你完成的事情的數據,相信我,人人都喜歡聽故事
- 你爲什麼想得到這份工作?
- 你解決過的最有難度的問題是什麼?
- 面對過的最大挑戰是什麼?
- 見過的最好或者最壞的設計是怎麼樣的?
- 對某項 Google 產品提出改進建議。
- 你作爲一個個體同時也是團隊的一員,如何達到最好的工作狀態?
- 你的什麼技能或者經驗是你的角色中不可或缺的?爲什麼?
- 你在某份工作或某個項目中最享受的是什麼?
- 你在某份工作或某個項目中面臨過的最大挑戰是什麼?
- 你在某份工作或某個項目中遇到過的最蛋疼的 Bug 是什麼樣的?
- 你在某份工作或某個項目中學到了什麼?
- 你在某份工作或某個項目中哪些地方還可以做的更好?
問面試官的問題
我會問的一些:(可能我已經知道了答案但我想聽聽面試官的看法或者瞭解團隊的前景):
- 團隊多大規模?
- 開發週期是怎樣的? 會使用瀑布流/極限編程/敏捷開發麼?
- 經常會爲 deadline 加班麼? 或者是有彈性的?
- 團隊裏怎麼做技術選型?
- 每週平均開多少次會?
- 你覺得工作環境有助於員工集中精力嗎?
- 目前正在做什麼工作?
- 喜歡這些事情嗎?
- 工作期限是怎麼樣的?
當你獲得了夢想的職位
我還能說些什麼呢,恭喜你!
堅持繼續學習。
得到這份工作只是一個開始。
*****************************************************************************************************
*****************************************************************************************************
下面的內容都是可選的。這些是我的推薦,不是 Google 的。
通過學習這些內容,你將會得到更多的有關 CS 的概念,並將爲所有的軟件工程工作做更好的準備。
*****************************************************************************************************
*****************************************************************************************************
附加的學習
Unicode
字節順序
- [ ] 大、小端字節序
- [ ] 大端字節 Vs 小端字節(視頻)
- [ ] 大、小端字節序的裏裏外外(Big And Little Endian Inside/Out) (視頻)
- 內核開發者的討論非常技術性,如果大多數都超出了你的理解範圍,不要太擔心。
- 前半段已經足夠了。
Emacs and vi(m)
- Yegge 的建議,從一個很早以前的亞馬遜招聘信息中而來:熟悉基於 unix 的代碼編輯器
- vi(m):
- emacs:
Unix 命令行工具
信息資源 (視頻)
- [ ] Khan Academy 可汗學院
- [ ] 更多有關馬爾可夫的內容:
- 關於更多信息,請參照下方 MIT 6.050J 信息和系統複雜度的內容.
奇偶校驗位 & 漢明碼 (視頻)
系統熵值(系統複雜度)
- 請參考下方視頻
- 觀看之前,請先確定觀看了信息論的視頻
- [ ] 信息理論, 克勞德·香農, 熵值, 系統冗餘, 數據比特壓縮 (視頻)
密碼學
壓縮
- 觀看之前,請先確定觀看了信息論的視頻
- [ ] 壓縮 (視頻):
- [ ] 壓縮
- [ ] 壓縮熵值
- [ ] 由上而下的樹 (霍夫曼編碼樹)
- [ ] 額外比特 - 霍夫曼編碼樹
- [ ] 優雅的壓縮數據 (無損數據壓縮方法)
- [ ] Text Compression Meets Probabilities
- [ ] 數據壓縮的藝術
- [ ] (可選) 谷歌開發者: GZIP 還差遠了呢!
網絡 (視頻)
- [ ] 可汗學院
- [ ] 網絡傳輸協議中的數據壓縮
- [ ] TCP/IP 和 OSI 模型解析!
- [ ] TCP/IP 教程:傳輸數據包.
- [ ] HTTP
- [ ] SSL 和 HTTPS
- [ ] SSL/TLS
- [ ] HTTP 2.0
- [ ] 視頻
- [ ] 子網絡解密 - 第五部分 經典內部域名指向 CIDR 標記
計算機安全
釋放緩存
- [ ] Java 釋放緩存; 片段化數據 (視頻)
- [ ] 編譯器 (視頻)
- [ ] Python 釋放緩存 (視頻)
- [ ] 深度解析:論釋放緩存在 JAVA 中的重要性
- [ ] 深度解析:論釋放緩存在 Python 中的重要性(視頻)
並行/併發編程
設計模式
- [ ] UML統一建模語言概覽 (視頻)
- [ ] 主要有如下的設計模式:
- [ ] s(strategy)
- [ ] singleton
- [ ] adapter
- [ ] prototype
- [ ] decorator
- [ ] visitor
- [ ] factory, abstract factory
- [ ] facade
- [ ] observer
- [ ] proxy
- [ ] delegate
- [ ] command
- [ ] state
- [ ] memento
- [ ] iterator
- [ ] composite
- [ ] flyweight
- [ ] 第六章 (第 1 部分 ) - 設計模式 (視頻)
- [ ] 第六章 (第 2 部分 ) - Abstraction-Occurrence, General Hierarchy, Player-Role, Singleton, Observer, Delegation (視頻)
- [ ] 第六章 (第 3 部分 ) - Adapter, Facade, Immutable, Read-Only Interface, Proxy (video)
- [ ] 視頻
- [ ] Head Fisrt 設計模型
- 儘管這本書叫做設計模式:重複使用模塊,但是我還是認爲Head First是對於新手來說很不錯的書。
- [ ] 基於實際操作對於入門開發者的建議
信息傳輸, 序列化,和隊列化的系統
- [ ] Thrift
- [ ] 協議緩衝
- [ ] gRPC
- [ ] Redis
- [ ] Amazon的 SQS 系統 (隊列)
- [ ] Amazon的 SNS 系統 (pub-sub)
- [ ] RabbitMQ
- [ ] Celery
- [ ] ZeroMQ
- [ ] ActiveMQ
- [ ] Kafka
- [ ] MessagePack
- [ ] Avro
- [ ] Thrift
快速傅里葉變換
- [ ] 什麼是傅立葉變換?論傅立葉變換的用途
- [ ] 什麼是傅立葉變換? (視頻)
- [ ] 關於 FFT 的不同觀點 (視頻)
- [ ] FTT 是什麼
布隆過濾器
- 給一個布隆過濾器m比特和k個哈希函數,所有的注入和相關測試都會是通過。
- 布隆過濾器
- 布隆過濾器 | 數據挖掘 | Stanford University
- 教程
- 如何寫一個布隆過濾器應用
van Emde Boas 樹
- [ ] 爭論: van Emde Boas 樹 (視頻)
- [ ] MIT課堂筆記
更深入的數據結構
跳錶
- ”有一種非常迷幻的數據類型” - Skiena
- [ ] 隨機化: 跳錶 (視頻)
- [ ] 更生動詳細的解釋
網絡流
- [ ] 5分鐘簡析Ford-Fulkerson (視頻)
- [ ] Ford-Fulkerson 算法 (視頻)
- [ ] 網絡流 (視頻)
不相交集 & 聯合查找
快速處理數學
樹堆 (Treap)
- 一個二叉搜索樹和一個堆的組合
- [ ] 樹堆
- [ ] 數據結構:樹堆的講解(video)
- [ ] 集合操作的應用(Applications in set operations)
線性規劃(Linear Programming)(視頻)
幾何:凸包(Geometry, Convex hull)(視頻)
離散數學
- 查看下面的視頻:(這裏沒看到視頻= =)
機器學習(Machine Learning)
- [ ] 爲什麼學習機器學習?
- [ ] 谷歌雲機器學習工具(視頻)
- [ ] 谷歌開發者機器學習清單 (Scikit Learn 和 Tensorflow) (視頻)
- [ ] Tensorflow (視頻)
- [ ] Tensorflow 教程
- [ ] Python 實現神經網絡實例教程(使用 Theano)
- 課程:
- [ ] 很棒的初級課程:機器學習
- 視頻教程
- 看第 12-18 集複習線性代數(第 14 集和第 15 集是重複的)
- [ ] 機器學習中的神經網絡
- [ ] Google 深度學習微學位
- [ ] Google/Kaggle 機器學習工程師微學位
- [ ] 無人駕駛工程師微學位
- [ ] Metis 在線課程 (兩個月 99 美元)
- [ ] 很棒的初級課程:機器學習
- 資源:
- 書籍: Data Science from Scratch: First Principles with Python: https://www.amazon.com/Data-Science-Scratch-Principles-Python/dp/149190142X
- 網站: Data School: http://www.dataschool.io/
- [ ] 爲什麼學習機器學習?
Go 語言
- [ ] 視頻:
- [ ] 爲什麼學習 Go 語言?
- [ ] Go 語言編程
- [ ] Go 語言之旅
- [ ] 書籍:
- [ ] Go 語言新手訓練營
- [ ] 視頻:
–
一些主題的額外內容
我爲前面提到的某些主題增加了一些額外的內容,之所以沒有直接添加到前面,是因爲這樣很容易導致某個主題內容過多。畢竟你想在本世紀找到一份工作,對吧?
[ ] 動態規劃的更多內容 (視頻)
[ ] 圖形處理進階 (視頻)
- [ ] 異步分佈式算法: 對稱性破缺,最小生成樹
- [ ] 異步分佈式算法: 最小生成樹
[ ] MIT 概率論 (mathy, and go slowly, which is good for mathy things) (視頻):
- [ ] MIT 6.042J - 概率論概述
- [ ] MIT 6.042J - 條件概率 Probability
- [ ] MIT 6.042J - 獨立
- [ ] MIT 6.042J - 隨機變量
- [ ] MIT 6.042J - 期望 I
- [ ] MIT 6.042J - 期望 II
- [ ] MIT 6.042J - 大偏差
- [ ] MIT 6.042J - 隨機遊走
視頻系列
坐下來享受一下吧。”netflix and skill” :P
[ ] 離散數學 (19 個視頻)
[ ] CSE373 - 算法分析 (25 個視頻)
[ ] 斯坦福: 編程範例 (17 個視頻)
[ ] 密碼學導論