You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 KiB

Coding Interview University

原先我為了成為一個軟體工程師而建立這份簡單的讀書主題清單(To-do list) 但這份To-do list隨著時間而膨脹成這個樣子。 做完這份To-do list上的每個目標後我成為了Amazon的工程師! 你或許不需要像我讀一樣多。但是,每個讓你成為一位稱職工程師所需要的知識都在這裡了。

我每天讀8~12小時的書這樣持續了好幾個月。這是我的故事:為什麼我為了Google面試而讀了8個月

在這份To-do list內的主題會讓你擁有足夠的知識去面對幾乎每家軟體公司的專業面試 這些公司包含了科技巨獸例如Amazon、Facebook、Google或者是Microsoft。

祝你好運!

翻譯:
正在翻譯的項目:

What is it?

這是我為了從一個網頁開發者(自學,並且沒有任何與資工、電腦科學有關的學位),成為一個大公司軟體工程師,持續好幾個月的讀書計畫。

Coding at the whiteboard - from HBO's Silicon Valley

這是為了那些新手軟體工程師,或者是那些想要轉換跑道,從軟體/網頁開發者轉為軟體工程師(需要資工、電腦科學的知識)的人。

請注意就算你有多年的軟體/網頁開發經驗那些著名的大型軟體公司像是Google、Amazon、Facebook或是Microsoft事實上把軟體/網頁開發(Software/Web Development)與軟體工程(Software Engineering)視為不同,而後者需要的是電腦科學/資訊工程的知識。

如果你想成為一個可靠的工程師或者是Operation Engineer閱讀並且學習更多這份清單中的The Optional List(裡面包含網路與資訊安全的知識)。


目錄

---------------- 以下皆為選讀 ----------------

額外資源


Why use it?

當我開始這項計畫的時候我不知道Stack與Heap的差別不知道時間複雜度(Big-O),不知道樹狀結構(Tree),也不知道如何遍歷一個圖(Graph)。過去如果我需要寫一個排序演算法(Sorting Algorithm)那個code一定是個災難。我過去都用程式語言中內建的資料結構(Data Structure),對於資料結構裡面的實作方法跟原理我完全沒有任何的概念。除非我的程式碰到了"out of memory"的錯誤我才會去找解決方法,否則我從不特別去花費心思管理程式中的記憶體配置。雖然我有用過多維陣列(Multidimensional Arrays)跟關聯陣列(Associative Arrays),但我從來沒有自己時做過資料結構。

這是個遠大的計畫,或許要花上你數個月的時間。如果你對其中大部分的東西已經很熟悉的話,那麼執行這項計畫所花費的時間將減少許多。

How to use it

下面每項是大綱,你需要從上到下的去理解這些大綱。

我用了Github-flavored markdown語法其中包含了可以確定完成進度的任務清單。

建立一個新的Branch以使用Github-flavored markdown的勾選功能。只要在[]中打x像是: [x]

Fork一個branch並且跟隨以下的指令

git clone git@github.com:<your_github_username>/coding-interview-university.git

git checkout -b progress

git remote add jwasham https://github.com/jwasham/coding-interview-university

git fetch --all

在你完成了一些目標後在框框中打x

git add .

git commit -m "Marked x"

git rebase jwasham/main

git push --set-upstream origin progress

git push --force

更多有關Github-flavored markdown

Don't feel you aren't smart enough(不要覺得自己不夠聰明)

About Video Resources(關於影片資源)

有些影片要註冊Coursera或者Edx的課程後才能觀看也就是所謂的MOOCs。有時候某些課程需要等待好幾個月才能註冊這期間你無法觀看這些課程的影片。

我非常喜歡那些大學的線上課程。感謝你們幫忙加入一些免費、可隨時觀看的公開資源像是那些線上課程的YouTube影片。

Interview Process & General Interview Prep(面試過程&面試準備)

面試時專精一種程式語言(Pick One Language for the Interview)

在面試的coding階段你可以選擇任何一個你擅長的程式語言。但多數大公司僅有以下選擇:

  • C++
  • Java
  • Python

你也可以選擇以下的程式語言,但可能會有某些限制:

  • JavaScript
  • Ruby

我之前寫過一篇關於在面試時選擇程式語言的文章:Pick One Language for the Coding Interview

你需要非常熟練這個程式語言,並且對他非常了解。

閱讀更多有關程式語言的選擇:

程式語言相關資源

因為我正在學習C、C++以及Python所以下面會出現一些有關於這些程式語言的資源。

書單(Book List)

為了節省你的時間,以下是已經縮減過的書單。

面試準備(Interview Prep)

如果你有額外的時間(If you have tons of extra time):

選擇以下其中一個:

程式語言精進

面試時你需要選擇一種程式語言(詳如上述)

以下是一些我對程式語言的建議。這邊沒有所有種類程式語言的資源,所以歡迎補充。

如果你讀過以下其中一本你應該已經具備了所有解決coding問題所需要的資料結構與演算法的知識。除非你想要複習否則你可以跳過這個計畫中所有的教學影片

額外程式語言精進資源

C++

我沒讀過這兩本書但他們頗受好評。作者是Sedgewick他超讚的!

如果你有更好的C++書籍,請告訴我。我正在蒐集全面性的資源。

Java

或者:

  • Data Structures and Algorithms in Java
    • 作者:Goodrich、Tamassia、Goldwasser
    • 被作為UC Berkeley資工系入門課程的補充教材
    • 看看下面我對這本書的Python版的書評。兩本書都包含了相同的主題。

Python

在你開始之前

這份清單隨著時間越來越大。當然,這也同時代表我越來越難以掌握他的整體內容。

以下是一些清單內的錯誤,希望能讓你避免這些錯誤,並且有更好的學習體驗。

1. 你沒辦法記住所有事情

我看了數小時的影片,同時也寫下了大量的筆記。但過了幾個月後,大部分的東西都消失的無影無蹤。我花了三天重新看過我的筆記,並做了小字卡幫助我複習他們。

請閱讀以下的文章以免重蹈覆轍:

Retaining Computer Science Knowledge.

有人推薦給我的課程(但我還沒看過:( ): Learning how to Learn

2. 使用小字卡

為了解決剛剛提到的遺忘問題,我自己寫了一個小字卡網站。網站上可以新增兩種小字卡,一般的以及程式碼。 每一種類的小字卡都有不同的格式。

這個小字卡網站在製作時便是以行動裝置優先的方式設計的,好處是無論我在何處,我都可以在我的手機與平板上複習。

製作屬於自己的免費小字卡:

我的小字卡資料庫中包含了組合語言、Python的小知識、機器學習以及統計。這些內容已經超出了原本他的預設。

關於小字卡:當你第一次知道答案後,別馬上把那張小字卡標記為已知。反覆複習這張小字卡,直到每次都能答對後才是真正學會了這個問題。反覆的動作會讓這個知識深深地烙印在你的腦海內。

這裡有個替代我小字卡的網站Anki,很多人向我推薦過他。這個網站用同一個字卡重複出現的方式讓你牢牢地記住他。 這個網站非常容易使用支援多平台並且有雲端同步功能。在iOS平台上收費25美金其他平台免費。

這是我用Anki這個網站裡的格式所儲存的小字卡資料庫: https://ankiweb.net/shared/info/25173560 (感謝 @xiewenya)

3. 學習資料結構與演算法的同時也要做一些Coding面試中常出現的問題

把你學過的東西應用在解題上面否則你很快就會忘了他們。這是一個過來人的經驗談。一旦你自認學會了一個主題像是Linked List之類的打開任何一本Coding面試問題書籍做一些裡面有關Linked List的問題。接著繼續讀後面的主題。然後再回頭反覆做有關Linked List、遞迴或者其他任何東西(原文為Recursion非Recursive)的題目。但切記一定在讀這些資料結構、演算法的同時,也要實際去寫一些有關這些東西的題目。公司錄取你是為了能有即戰力能夠上戰場,而非一個紙上談兵的人。這邊我覺得還不錯的書籍和網站。更多: Coding Question Practice

4. 複習,複習,再複習

我自己寫了一些有關於ASCII Code、網路OSI模型、Big-O(時間複雜度)等等的小抄。我有空的時候就會把他們拿出來看一看複習一下。

打Code累了的話就休息半個小時並且複習你的小字卡。

5. 專注

能夠干擾你,浪費你寶貴時間的東西很多。因此,專注集中精神實在很難。放點純音樂能幫上一些忙。

這份清單沒有包含的內容

以下為普遍但沒有包含在這份清單內的技術:

  • SQL
  • Javascript
  • HTML、CSS以及其他前後端的技術

每日計畫

每個主題所花費的時間都不盡相同,有些只要一天,有些需要花上數天。有些主題只有單純的知識而無包含實作。

每天我選擇下面其中一個主題,看跟該主題相關的影片,再用下面的程式語言實作:

  • C - 用使用了struct *或者其他東西當作參數的struct以及函數
  • C++ - 不要使用內建的東西
  • C++ - 用C++內建的東西像是STL的Linked Liststd::list。
  • Python - 使用內建的東西(為了練習Python)
  • 寫一些測試來驗證自己寫的東西是正確的像是用assert()等簡單的方法。
  • 你也可以用Java來練習上面只是我自己的方法。

你不需要學會所有的程式語言,你只需要專精在某個程式語言 one language for the interview.

為什麼要這樣寫Code?

  • 練習練習再練習直到我對他產生厭惡感並且能輕鬆無誤地寫出那些Code。(有些東西需要特別記住,像是在邊界的時候會出現問題(edge cases),或者一些小細節)
  • 全部自己來(像是手動分配/釋放記憶體不要依賴語言中的garbage collection的功能(除了Python或者Java))
  • 利用語言中內建的東西及工具,之後在實際工作的時候才能得心應手(畢竟我不想在工作時手刻一個Linked List)。

我沒有時間做每個主題中的每個東西,但我會盡力而為。

下面是我自己寫的程式碼:

你不需要記住每個演算法裡面的內容。

試試看把程式碼寫在白板或者紙上而不是電腦上。接著用一些測資來測試他。最後才用電腦來驗證。

先備知識

演算法複雜度(Algorithmic complexity) / Big-O / 漸進分析(Asymptotic analysis)

資料結構

  • 陣列

    • 實作一個可以自動調整大小的陣列(動態陣列vector)
    • (動態)陣列背後原理:
    • 實作動態陣列(可變、可動態調整大小的陣列)
      • 練習在程式中用陣列以及指標,透過計算指標而存取該內容,而不是直接用索引。
      • 直接動態生成一個新的陣列
        • 可以生成一個int型別的陣列但不要使用語言提供的功能
        • 從16或者更大的數開始寫像是2的次方 - 16、32、64、128。
      • size() - 陣列中元素個數
      • capacity() - 陣列能存的最大元素個數
      • is_empty()
      • at(index) - 傳回該索引值的元素,附有邊界檢查(boundary check)
      • push(item)
      • insert(index, item) - 把元素插入該索引值,把原本在該索引值的元素往右邊移動。
      • prepend(item) - 可以把元素插入索引值為0的地方。
      • pop() - 移除陣列中最後一個元素,並回傳該元素的值。
      • delete(index) - 刪除在該索引值的元素,並且把右邊剩下元素全部往左移。
      • remove(item) - 從陣列中尋找該數值,並且移除他(就算陣列中數個地方都有這個數值)。
      • find(item) - 從陣列中尋找該數值,並且傳回最前面找到該數值的索引值,如果沒有則傳回-1。
      • resize(nex_capacity) // private function
        • 當陣列已經用盡了所有容量後,把陣列的容量*2。
        • 如果移除掉一個元素後陣列實際大小是最大容量的1/4則把陣列容量減半。
      • 時間複雜度
        • O(1) 在陣列末端插入/刪除元素
        • O(n) 在任何地方插入/刪除元素
      • 空間複雜度
        • 在記憶體中的存放位置是連續的,這種儲存方式有助於存取的性能。
        • 所需空間 = (陣列容量,>=n) * 元素所需大小但就算結果為2n實際上仍算成O(n)
  • Linked Lists

    • Linked Lists背後原理:
    • C Code (video) - 沒有完整的code裡面只包含了用struct實作節點的方式以及其記憶體配置。
    • Linked List vs 陣列:
    • why you should avoid linked lists (video)
    • 小心!: 你需要一些關於指標的指標(Pointer to pointer)的知識: (當你回傳一個指標到函式,這個動作可能會改變指標所指向的地址) 這個頁面僅提供基本對於指標的指標的認識。我不推薦這個遍歷linked list的方式因為他用的方式太過神奇所以可讀性以及維護性並不好。
    • 實作Linked list (我做了有末端指標(tail pointer)的版本以及無末端指標的版本):
      • size() - 回傳linked list裡面的元素個數
      • empty() - 回傳型態:bool如果linked list為空回傳true
      • value_at(index) - 回傳索引值為index的元素的數值第一個元素索引值為0以此類推
      • push_front(value) - 從linked list的起始點加入新的元素
      • pop_front() - 移除第一個元素,並且回傳該元素的數值
      • push_back(value) - 在linked list末端加入新元素
      • pop_back() - 移除最後一個元素,並且回傳該元素的數值
      • front() - 回傳第一個元素的數值
      • back() - 回傳最後一個元素的數值
      • insert(index, value) - 把新元素插入到該索引值,而新元素指向原本在該索引值的元素。
      • erase(index) - 刪除該索引值的元素(節點)
      • value_n_from_end(n) - 回傳從末端開始計算的第n個元素的數值
      • reverse() - 反轉該linked list
      • remove_value(value) - 刪除第一個為該數值的元素(意即7 2 2 1要刪除2的話只刪除index:1的那個2)
    • 雙向linked List
  • Stack(堆疊)

  • Queue(佇列)

    • 使用Queues(先進先出)First-In First-Out(影片)
    • Queue(影片)
    • Circular buffer/FIFO
    • Priority Queues(影片)
    • [Review] Queues in 3 minutes (video)
    • 使用linked list實作包含末端指標(tail pointer):
      • enqueue(value) - 在queue末端加入元素
      • dequeue() - 刪除當時queue中最早進入的元素(意即queue中第一個元素),並且回傳該元素的值。
      • empty()
      • full()
    • 複雜度:

      • enqueue: O(1) (平均情況無論對於用linked list或陣列實作的方法)
      • dequeue: O(1) (linked list與陣列)
      • empty: O(1) (linked list與陣列)
  • Hash table(雜湊表)

更多

樹狀結構(Tree)

排序

這裡有15種排序演算法的影片,如果你想對排序演算法有更多的了解,看看Additional Detail on Some Subjects裡的「排序」這個部分

圖在電腦科學中可以用來表示、處理很多問題,所以這個部分就像樹以及排序一樣篇幅很長。

更多知識

系統設計、可擴充性、資料處理

如果你已經擁有了4年以上的程式經驗那你可以來看看有關系統設計的問題


總複習

這部分我放了一些簡短的影片,觀看這些影片可以快速的複習一些重要的觀念。
如果你想時常複習,那真是太棒了!

解題練習

現在你已經知道上面所有有關電腦科學的主題了,該是時候做些解題的練習了。

解題練習不能死記題目的解法

為什麼你需要練習解題:

  • 快速識別問題,以及如何應用正確的資料結構及演算法。
  • 蒐集問題的需求
  • 模擬面試時用你的方法闡述問題
  • 試著不要在電腦上寫程式,而是 在白板上或紙上
  • 想出該問題的時間與空間複雜度
  • 測試你的解法

這裡有個很棒的入門教學,內容是如何在面試中有條不紊,並且有互動溝通地解決問題。這種能力可以從面試書籍中獲得,但我覺得這個也超讚的:Algorithm design canvas

家裡沒有白板嗎?這很合理。但我是個奇怪的人,家裡有個大白板。沒有白板的話,可以去美術社買個大的繪圖板。你可以坐在沙發上練習。這是我的「沙發白板」。我在照片中放了一枝筆當作比例尺。如果你用筆的話,你將會希望你可以擦拭他,因為他很快就會變髒了。通常我都用鉛筆與橡皮擦。

my sofa whiteboard

補充:

閱讀並解題(按照以下順序):

看看上方的書單

解題練習/挑戰

學了一些東西之後,可以開始試試每天解一些題目,越多越好!

Coding面試題目影片:

解題網站:

解題repository:

更多面試:

面試前夕

你的履歷

  • 看看Coding面試解密中的履歷準備。

想想面試時可能的狀況

一些我預想的問題(我或許已經知道答案,但想知道他們的意見或是團隊的觀點):
  • 你的團隊規模多大?
  • 你的開發週期大概是怎樣?敏捷agile、瀑布式waterfall、sprint?
  • 截止日前趕工是常態嗎?或是這之中有彈性?
  • 在你的團隊中是怎麼做決定的?
  • 每週你們開幾次會?
  • 你覺得你的工作環境能幫助你專注嗎?
  • 你目前在做哪個專案?
  • 你喜歡這個專案的哪個部份?
  • 工作生活如何?
  • 工作與生活如何取得平衡?

一旦你得到工作

恭喜!!!

繼續學習

活到老,學到老。


*****************************************************************************************************
*****************************************************************************************************

下面的東西都是額外的。
讀這些東西,可以更了解電腦科學的概念,
並且能讓自己對任何軟體工程的工作做更好的準備。
如此一來,你將會成為一個更全面的軟體工程師。

*****************************************************************************************************
*****************************************************************************************************

選修書籍

你可以從以下的書單挑選你有興趣的主題來研讀
  • The Unix Programming Environment

    • 老,但卻很棒
  • The Linux Command Line: A Complete Introduction

    • 現代選擇
  • TCP/IP Illustrated Series

  • Head First Design Patterns

    • 設計模式的入門簡介
  • Design Patterns: Elements of Reusable Object-Oriented Software

    • 也被稱為"四人幫"("Gang of Four(GOF)")
    • 經典設計模式書籍
  • UNIX and Linux System Administration Handbook, 5th Edition

  • Algorithm Design Manual (Skiena)

    • 作為複習以及問題辨別
    • 這本書中演算法的部分難度已經超過面試會出現的
    • 本書分為兩個部分:
      • 資料結構及演算法課本
        • 優點:
          • 跟其他演算法課本一樣是個很棒的複習素材
          • 內含關於作者以往解決工業及學術上問題的經驗的故事
          • 含C語言程式碼範例
        • 缺點:
          • 某些地方跟"Introduction to Algorithms"一樣艱深,但在某些主題,"Introduction to Algorithms"或許是更好的選擇。
          • 第7、8、9章有點難以消化因為某些地方並沒有解釋得很清楚或者根本上我就是個學渣
          • 別會錯意了我很喜歡Skiena的教學方法以及他的風格。
      • 演算法目錄:
        • 這個部分是買這本書的最大誘因
        • 我即將著手進行這部分,一旦完成這部分我會再更新上來
      • 可以在kindle上租
    • 解答:
    • 勘誤表
  • Write Great Code: Volume 1: Understanding the Machine

    • 這本書出版於2004年某些程度上他有點過時了但對於初步理解電腦是個很棒的資源
    • 作者發明了高階組合語言HLA所以提到並且舉了一些HLA的例子。裡面沒有用到很多但都是很棒的組合語言的例子。
    • 這些章節很值得一讀,讓你具備極佳的基礎:
      • 第2章 - 數值表示法
      • 第3章 - 二進位運算和位元運算
      • 第4章 - 浮點數表示法
      • 第5章 - 字元表示法
      • 第6章 - 記憶體組織和存取
      • 第7章 - 複合資料型別和記憶體
      • 第9章 - CPU架構
      • 第10章 - 指令集架構
      • 第11章 - 記憶體架構與組織
  • Introduction to Algorithms

    • 重要: 讀這本書CP值不高。這本書作為複習演算法和資料結構還算滿不錯的但它裡面沒有教你怎麼實作這些東西。你必須要能夠自己寫出很棒、有效率的解法。
    • 也被稱為CLR或是CLRS因為Stein是後來才加入作者群的。
  • Computer Architecture, Sixth Edition: A Quantitative Approach

    • 更豐富、更新(2017年),但篇幅較長。
  • Programming Pearls

    • 前幾章提供了一些解決coding問題的精妙絕倫的方法(有些很舊,甚至還用磁帶),但那些只是導論。這是本程式設計和架構的指南。

額外學習

我把他們加了進來為了讓你成為更全方位的軟體工程師,並且留意一些科技以及演算法,讓你的資料庫中有更多素材。

某些主題的額外知識

我為了強化某些已經在上面呈現的內容,所以才增加這些東西。但因為上面已經有太多內容了,所以不想把這些放在上面。
You want to get hired in this century, right?

影片系列

坐下來享受一下"Netflix和技巧" :P

電腦科學課程

論文

LICENSE

CC-BY-SA-4.0