-
1 # 小旋風新鮮事
-
2 # 樂得開了花啦
可以自學,按照入門和精深的層級買幾本書多看多練,書籍不用多但求精;其次,可以看看網上的課程,從入門開始,慢慢學習別人的經驗和心得;最後,充分充分實踐,多上手實操,多謝程式碼並讓專家執政,總結經驗。
-
3 # 小小猿
一、什麼是演算法
演算法是解決問題方案的準確而且完整的描述,透過一系列明確的指令解決問題。不同的演算法在解決相同的問題時,所消耗的時間、空間效率不同。所以我們用時間複雜度和空間複雜度來衡量一個演算法的優劣。[1]
二、演算法的特徵[1]
有窮性:一個合法的演算法必然能透過有限個步驟解決問題。
確切性:演算法的每個步驟都有明確的意義。
輸入項:一個演算法必然有 0 個或多個輸入項。
輸出項:一個演算法必然有 1 個或多個輸出項,沒有結果輸出的演算法毫無意義
可行性:演算法在解決問題時,每一個步驟都可以在有限的時間內完成。
三、時間複雜度 & 空間複雜度
1. 時間複雜度
時間複雜度是一個函式,記為 O(n),它用來描述演算法執行的時間。[2]
那麼讓我們來舉個栗子:
現在我們有一塊蛋糕,要分給4個小朋友,在不考慮每個小朋友分到蛋糕大小相等的情況,我們要如何切蛋糕呢?
首先我們可以十字刀切蛋糕,這樣兩刀我們就可以把蛋糕分好了。還有什麼辦法呢?因為我們不關心蛋糕的大小,所以我們也可以同方向平行的切三刀把蛋糕分成四塊。
好了,那麼我們可以發現,我們可以用兩刀解決問題、也可以用三刀解決問題,這裡用了幾刀解決了問題就是我們的時間複雜度。
通常我們使用演算法的最壞情況複雜度,記為 T(n) ,定義為任何大小的輸入n所需要最大的執行時間。上面兩個切蛋糕的方案,我們可以分別記為 T(n) = 2n \ T(n) = 3n。
接下來我們又遇到了新的問題了,有的小夥伴使用塑膠餐刀切蛋糕用了五分鐘才切好一刀,有的小夥伴使用40米大刀一秒切好一刀,他們都是用了兩刀把蛋糕切好了,誰的速度更快呢?
這個問題就是在我們都是切了兩刀,但是使用的切刀不同,也會導致我們分配蛋糕的時間變長。
所以我們使用了漸進時間複雜度:假設問題輸入項有n個,當n趨於無窮大的時候,O(n)所得到的極限值。[3]
舉個栗子,現在我們有兩個演算法,它們的時間複雜度分別為:
T(n) = 3n^2 + 2n + 1 和 T(n) = 100n^4 + 999
先看一個公式:T(n) = 3n^2 + 2n + 1。當n趨於無窮大的時候,最後的1可以忽略不計了。接下來看 3n^2 和 2n ,我們發現當n越大的時候,兩者差距就越大,當n趨於無窮大的時候,3n^2 遠遠大於 2n,所以2n我們也可以忽略不計了。最後我們只剩下 3n^2 ,當n無窮大的時候,它再乘以3貌似對結果變得更大沒有起到質的變化,所以我們省略掉3。最後我們剩下來最終的結果:T(n) = n^2
在看第二個公式:T(n) = 100n^4 + 999。當n趨於無窮大的時候,999已經無足輕重了,自動忽略。從上一個公式的經驗,我們就會自然忽略 100,最終剩下 T(n) = n^4
最終我們對比兩個公式的優劣的時候,自然可以看出來當n越來越大的時候,第二個公式會比第一個公式耗時更長,所以第一個公式更好。
那麼如果出現了公式:T(n) = 3n^5 + 100n^3 + 10n^2,這種情況呢?按照我們第一個公式忽略的方案,當n趨於無窮大的時候,n^5要遠遠比n^3和n^2大,所以自然我們忽略掉 100n^3 和10n^2,只保留n^5,最終結果是 T(n) = n^5。
最終我們來總結一下時間複雜度:
它是一個描述演算法執行時間的函式 O(n)
推導一個演算法的時間複雜度,首先忽略常數、只保留函式中的最高階、省去最高階項的係數[4]
2. 空間複雜度
空間複雜度是指在演算法執行中時臨時儲存空間大小的量度,記為 S(n) = O(f(n))。[5] 簡單來說就是,我們在程式碼執行中所佔的記憶體大小。
那麼如何去評定空間複雜度呢?方式和時間複雜度類似,我們也是根據輸入項n來做判斷。
舉個栗子,現在我們要向一個數組插入一條新的資料,這個操作不會有額外的記憶體佔有,所以它的空間複雜度是 S(n) = O(1)
再舉個栗子,我們現在要使用遞迴去解決一個問題,那麼就存在每次向下遞迴時,都需要臨時儲存一下我們的資料,所以當遞迴至最底層時,臨時儲存了n個數據,所以它的空間複雜度是 S(n) = O(n)
最終我們來總結一下空間複雜度:
它是指演算法執行中所佔用臨時空間大小的量度
如果沒有額外的臨時空間佔用,則空間複雜度為 O(1)
額外佔用空間是以輸入項n為比例計算的
回覆列表
首先你要明確學習和使用演算法的目的,當你確定走這條路了,就堅定信心,在這條路上不斷地努力學習,就一定可以做好!
明確學習和使用演算法的目的。
一個排序功能,用氣泡排序法,歸併排序法,快速排序法?who tm care。一個原生sort函式直接搞定。這就是實用場景,快速實現你的功能即可。
那需不需要學習各種排序演算法呢?需要,因為各種排序演算法用了很多不用的手段,知識去實現同一個功能,學習裡面的知識和優劣對比方法是很有用。
演算法其實算是一種簡稱,其實應該叫做演算法設計,不是說你能夠默寫幾個書上的演算法程式碼就叫會演算法了,而是能夠利用裡面的知識點去解決一些書本沒有的具體問題實現具體功能,我們學習的是這種能力,而不是死記硬背的知識。
還有就是學習演算法有利於面試,有利於工作交流,有利於抓住跨領域的進階機會。
你以為我馬上會推薦你去學排序嗎?
NO!
在前端你覺得你演算法差可能是因為你不熟悉javascript,更準確的說是ECMAscript的API。
首先,去了解一下常用的JavaScript Array和Object,能夠靈活運用足以解決初和中級常見的演算法問題。
第二步就是當你覺得一些原生api不夠用的時候就去用用lodash和underscore外掛。
第三步就是研究lodash或者underscore的原始碼,假如你這的能夠做到第一步說的靈活運用,那這一步也不會有什麼困難。
第四步寫自己的資料處理外掛,如無實際需要可以跳過這步,我就因為我經常要計算一個複雜陣列物件的複雜聚合運算(如過濾過後分組,計算最大,最小,平均,和等等),於是就在前端模擬SQL的語法做了一個外掛。
第五步才是學習演算法,建議學《演算法導論》,貼個連結,網易公開課,麻省理工的公開課,中文字幕。我也在看,需要大學高數知識。基本的排序應該要懂的。其他我也沒有往深裡面專研,主要想知道里面有什麼知識點,將來遇到解決不了的演算法問題起碼有個研究思路。