原文連接javascript
爲何要寫算法系列教程呢?由於最近剛看完《Algorithms, 4th Edition》這本經典算法書(電子書,中英版網上都有下載),有了些新收穫,以爲那些零散的知識點和經驗有必要也值得花時間好好整理一下。另外,我本身的算法知識應該尚未達到去學好「機器學習」這門學科的程度,在寫教程的同時我也會不斷學習,我想和你們一塊兒用算法這把鑰匙開啓「機器學習」這扇大門,去探索算法是如何讓機器「學習」的。java
爲何要學習算法呢?我我的以爲最終目的仍是爲了提升本身的職場競爭力。算法的本質就是解決問題,因此學習算法本質上是在提升解決問題的能力,這是職場最重要的能力之一。另外,若是你想在面試中表現得更加出色,也要對算法有必定程度的掌握。git
寫教程是很耗費精力的,並且學習算法是很枯燥的,但若是你們都能參與進來一塊兒交流討論,那麼整個過程就是不斷進行頭腦風暴、集思廣益的過程,這會是我繼續寫做的動力,這也會使得枯燥的算法學習之路變得有趣,並讓每一個人收穫滿滿。程序員
爲了更方便你們利用碎片化的時間學習,更好的利用空閒時間在手機上閱讀,這個系列的每一篇文章我都會精心排版,並且每一篇文章閱讀時間都不會太長,會盡可能控制在 6 分種之內(不包括思考的時間)。github
這個系列會包含三部份內容。第一部分是算法基礎,因爲算法和數據結構是密切相關的,因此也會講到一些數據結構的知識,但不會講太細。第二部分以常見的算法案例解析爲主,包括解析一些算法面試題。第三部分是算法在機器學習中的應用,因爲我本身也沒有學習過機器學習,因此這部分是探索式和交流式的,我會把我學到的用我理解寫出來,但願你們能參與進來一塊兒交流。面試
這個系列的文章代碼選擇用 JavaScript 語言來編寫,程序語言都是相通的,我相信你看了 JavaScript 寫的算法實現能夠很快用你熟悉的語言寫出來。但第三部分的機器學習相關內容,可能選用 Python,如今還不肯定。算法
但願這個算法系列教程能幫助你們在從此的編程道路上駕輕就熟。編程
好了,咱們今天以一個算法問題 FizzBuzz 來開篇吧。FizzBuzz 是一個很是典型的用來面試的算法題。下面是 FizzBuzz 的天然語言描述:數據結構
編寫一個程序,打印 1 到 100 中的數字,但能被 3 整除的變爲「Fizz」,能被 5 整除的變爲「Buzz」,既能被 3 整除又能被 5 整除的變爲「FizzBuzz」。機器學習
一看是否是很簡單?確實很簡單。看完題,隨手就能寫出下面的代碼:
for (var i = 1; i < 101; i++) {
if (i % 3 == 0) console.log('Fizz')
else if (i % 5 == 0) console.log('Buzz')
else if (i % 3 == 0 && i % 5 == 0) console.log('FizzBuzz')
else console.log(i)
}
複製代碼
和需求吻合,好像沒什麼問題。等等,仔細檢查,這段代碼問題大了,FizzBuzz
永遠沒有輸出的機會,例如遇到 i=15 仍是會輸出Fizz
。這是初級程序員很容易犯的一個錯誤,拿到需求後直接就是一通寫,對需求的理解比較生硬,不容易考慮到上下文的關聯關係。糾正後的寫法是將第 4 行的 if 條件放到最前面:
for (var i = 1; i < 101; i++) {
if (i % 3 == 0 && i % 5 == 0) console.log('FizzBuzz')
else if (i % 3 == 0) console.log('Fizz')
else if (i % 5 == 0) console.log('Buzz')
else console.log(i)
}
複製代碼
這樣寫是對的,但若是是面試,這個答案只能算是及格。如何能作到優秀呢?我總結寫算法能夠分爲三個步驟:
第一步是實現,即按照需求把算法寫對了,讓程序能正確的運行;第二步是優化,即下降複雜度,讓程序運算更高效。第三步是美化,即讓代碼看起來美觀簡潔,這一步不少時候會靈活運用到程序語言自己的語法糖,但簡潔有時候會犧牲代碼的易讀性,這須要在實際場景中稍做權衡。
作到這三步,我以爲應對面試中的算法題就能夠拿優秀了。
前面咱們已經完成了寫 FizzBuzz 算法的第一步,咱們再來作第二步:優化。既能被 3 整除又能被 5 整除,咱們很天然會想到 3 和 5 的最小公倍數:15,能被 15 整除的數必定也是既能被 3 整除又能被 5 整除的。也就是說上面的第二行代碼能夠只對 i
判斷一次(而不是兩次),下面是優化後的代碼:
for (var i = 1; i < 101; i++) {
if (i % 15 == 0) console.log('FizzBuzz')
else if (i % 3 == 0) console.log('Fizz')
else if (i % 5 == 0) console.log('Buzz')
else console.log(i)
}
複製代碼
咱們再來看第三步:美化。上面咱們寫這個算法用了 6 行代碼(包括大括號),若是要減小代碼量,能減小到多少行呢?這裏給到 2 行的實現方案:
for (let i = 0; i < 100; )
console.log((++i % 3 ? '' : 'Fizz') + (i % 5 ? '' : 'Buzz') || i)
複製代碼
這個實現來自 Reddit 。固然也能夠寫成一行,但寫成兩行閱讀體驗更好。這段代碼很好理解,我就不解讀了,有疑問能夠在留言區留言提問。
最後,對於 FizzBuzz 算法問題,你有其它的實現方案嗎?歡迎在留言區討論。
Hi, 你們好,我是 LiamWang,若是你喜歡個人文章,也能夠在如下平臺關注我:
Hope you're having a great day 😊