摘要:遞歸算法是一種直接或者間接調(diào)用自身函數(shù)或者方法的算法。因此,分治策略一般用來解決子問題相互對立的問題,稱為標(biāo)準(zhǔn)分治,而動態(tài)規(guī)劃用來解決子問題重疊的問題。調(diào)用棧尾遞歸和手動優(yōu)化尾調(diào)用就是一個函數(shù)執(zhí)行的最后一步是將另外一個函數(shù)調(diào)用并返回。
輸出
斐波那契數(shù)列的四種寫法
讀參考文章列表算法復(fù)雜度中的O(logN)底數(shù)是多少
從斐波那契數(shù)列談?wù)劥a的性能優(yōu)化
冰與火之歌:時間與空間復(fù)雜度
看動畫輕松理解遞歸與動態(tài)規(guī)劃
JavaScript調(diào)用棧、尾遞歸和手動優(yōu)化
數(shù)據(jù)結(jié)構(gòu)與算法公開課
問自己幾個問題算法復(fù)雜度中的O(logN)底數(shù)是多少, log2N 和 log10N 有區(qū)別么?
復(fù)習(xí)時間復(fù)雜度、空間復(fù)雜度、時間復(fù)雜度從小到大
時間復(fù)雜度級數(shù)
循環(huán)與級數(shù)的關(guān)系
分治、遞歸,遞歸的時間復(fù)雜度
從一個數(shù)組中找出最大的兩個數(shù)
什么是動態(tài)規(guī)劃,時間復(fù)雜度多少
尾調(diào)用和普通調(diào)用有啥不一樣
問題解答1,常底數(shù)是無所謂的,logaN/logbN = logab, 是一個常數(shù)
2,時間復(fù)雜度:
代碼段執(zhí)行次數(shù)累加
空間復(fù)雜度:
除了輸入本身所占的空間之外,用于計算的所必須的空間量
時間復(fù)雜度從小到大
O(1)
3,Ep12 時間復(fù)雜度級數(shù)
算數(shù)級數(shù),與末項平房同階,
1+2+3+...n = O(n^2)
冪方級數(shù),比冪次高出一階:
1+2^2+3^2+4^2 +... n^2 = O(n^3);
1+2^3+3^3+4^3 +... n^3= O(n^4);
1+2^4+3^4+4^4+... n^4 = O(n^5);
幾何級數(shù)(a>1):與末項同階
a^0+a^1+a^2+... a^n = (a^(n+1) - 1)/(a-1) = O(a^n)
1+2+4+8 +... 2^n = 2^(n+1) -1 = O(2^n)
4,循環(huán)與級數(shù)的關(guān)系
for(let i = 0; i < n; i++) for(let j = 0; i < n; j++) 坐標(biāo)軸形成正方形,O(n^2) for(let i = 0; i < n; i++) for(let j = 0; i < j; j++) 坐標(biāo)軸形成三角形,O(n^2)
5,冰與火之歌:時間與空間復(fù)雜度
分治:將原問題分解為若干個規(guī)模較小但類似于原問題的子問題(Divide),「遞歸」的求解這些子問題(Conquer),然后再合并這些子問題的解來建立原問題的解。
遞歸算法是一種直接或者間接調(diào)用自身函數(shù)或者方法的算法。通俗來說,遞歸算法的實質(zhì)是把問題分解成規(guī)模縮小的同類問題的子問題,然后遞歸調(diào)用方法來表示問題的解。它有如下特點(diǎn):
1. 一個問題的解可以分解為幾個子問題的解 2. 這個問題與分解之后的子問題,除了數(shù)據(jù)規(guī)模不同,求解思路完全一樣 3. 存在遞歸終止條件,即必須有一個明確的遞歸結(jié)束條件,稱之為遞歸出口
遞歸算法的世界復(fù)雜度,得分好幾種
第一種:
遞歸中進(jìn)行一次遞歸調(diào)用的復(fù)雜度分析,如:二分查找法
不管怎么樣,最多調(diào)用了一次遞歸調(diào)用而已,這時候時間復(fù)雜度看什么時候跳出遞歸
第二種:
遞歸中進(jìn)行多次遞歸調(diào)用的復(fù)雜度分析
比如說斐波拉契數(shù)列,多次調(diào)用自身
所以時間復(fù)雜度等于遞歸樹中節(jié)點(diǎn)數(shù)總和,就是代碼計算的調(diào)用次數(shù)。
T(n) = 各層遞歸實例所需時間之和
= O(1) * (2^0 + 2 ^1 + ...2^n)
= O(1) * (2^(n+1) - 1)
= O(2^n)
空間復(fù)雜度:
一個程序執(zhí)行時除了需要存儲空間和存儲本身所使用的指令、常數(shù)、變量和輸入數(shù)據(jù)外,還需要一些對數(shù)據(jù)進(jìn)行操作的工作單元和存儲一些為現(xiàn)實計算所需信息的輔助空間。
6,從一個數(shù)組中找出最大的兩個數(shù)
算法一
先遍歷一遍,找出最大值的位置,x1, 時間復(fù)雜度為 n-1
再遍歷一遍,從剩下的n-2個數(shù)中,找最大值,時間復(fù)雜度為 n-2
總共 O(2n-3) = O(n)
算法二
x1是小值,x2是大數(shù)
如果值比x2大,替換x2
如果 x1
算法三
左邊找最大L1,右邊找最大 R1
L1
7,看動畫輕松理解遞歸與動態(tài)規(guī)劃
動態(tài)規(guī)劃能解決的問題分治策略肯定能解決,只是運(yùn)行時間長了。因此,分治策略一般用來解決子問題相互對立的問題,稱為標(biāo)準(zhǔn)分治,而動態(tài)規(guī)劃用來解決子問題重疊的問題。
將「動態(tài)規(guī)劃」的概念關(guān)鍵點(diǎn)抽離出來描述就是這樣的:
1.動態(tài)規(guī)劃法試圖只解決每個子問題一次
2.一旦某個給定子問題的解已經(jīng)算出,則將其記憶化存儲,以便下次需要同一個子問題解之時直接查表。
8.JavaScript調(diào)用棧、尾遞歸和手動優(yōu)化
尾調(diào)用:
就是一個函數(shù)執(zhí)行的最后一步是將另外一個函數(shù)調(diào)用并返回。
一般來說,如果方法a調(diào)用方法b, 那么b放到棧頂,棧指針指向棧頂, 當(dāng)前幀是b, 調(diào)用幀是a,
當(dāng)函數(shù)B執(zhí)行完成后,還需要將執(zhí)行權(quán)返回A,那么函數(shù)A內(nèi)部的變量,調(diào)用函數(shù)B的位置等信息都必須保存在調(diào)用幀A中。不然,當(dāng)函數(shù)B執(zhí)行完繼續(xù)執(zhí)行函數(shù)A時,就會亂套。
那么現(xiàn)在,我們將函數(shù)B放到了函數(shù)A的最后一步調(diào)用(即尾調(diào)用),那還有必要保留函數(shù)A的棧幀么?當(dāng)然不用,因為之后并不會再用到其調(diào)用位置、內(nèi)部變量。因此直接用函數(shù)B的棧幀取代A的棧幀即可。當(dāng)然,如果內(nèi)層函數(shù)使用了外層函數(shù)的變量,那么就仍然需要保留函數(shù)A的棧幀,典型例子即是閉包。
總得來說,如果所有函數(shù)的調(diào)用都是尾調(diào)用,那么調(diào)用棧的長度就會小很多,這樣需要占用的內(nèi)存也會大大減少。這就是尾調(diào)用優(yōu)化的含義。
// 尾調(diào)用錯誤示范1.0 function f(x){ let y = g(x); return y; } // 尾調(diào)用錯誤示范2.0 function f(x){ return g(x) + 1; } // 尾調(diào)用錯誤示范3.0 function f(x) { g(x); // 這一步相當(dāng)于g(x) return undefined } 1.0最后一步為賦值操作,2.0最后一步為加法運(yùn)算操作,3.0隱式的有一句return undefined
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100804.html
摘要:如果函數(shù)內(nèi)部還調(diào)用函數(shù),那就還有一個的調(diào)用幀,依次類推。等同于等同于如果所有函數(shù)都是尾調(diào)用,那么完全可以做到每次執(zhí)行時,調(diào)用幀只有一項,這將大大節(jié)省內(nèi)存。這就是尾調(diào)用優(yōu)化。尾遞歸函數(shù)調(diào)用自身,稱為遞歸。 前言 面某東,有一道題目是 實現(xiàn)一個斐波拉契數(shù)列, 已知第一項為0,第二項為1,第三項為1,后一項是前兩項之和,即f(n) = f(n - 1) + f(n -2)。 拿到這個題目,二...
摘要:根據(jù)該規(guī)則,返回第個斐波那契數(shù)。尾遞歸函數(shù)調(diào)用自身,稱為遞歸。一個前端眼中的斐波那契數(shù)列解斐波那契數(shù)列的實用解法調(diào)用棧尾遞歸和手動優(yōu)化尾調(diào)用優(yōu)化譯我從用寫斐波那契生成器中學(xué)到的令人驚訝的件事 斐波那契數(shù)列是以下一系列數(shù)字: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ... 在種子數(shù)字 0 和 1 ...
摘要:一個解決的辦法是從算法上解決,把遞歸算法改良成只依賴于少數(shù)狀態(tài)的迭代算法,然而此事知易行難,線性遞歸還容易,樹狀遞歸就難以轉(zhuǎn)化了,而且并不是所有遞歸算法都有非遞歸實現(xiàn)。 前言 眾所周知,遞歸函數(shù)容易爆棧,究其原因,便是函數(shù)調(diào)用前需要先將參數(shù)、運(yùn)行狀態(tài)壓棧,而遞歸則會導(dǎo)致函數(shù)的多次無返回調(diào)用,參數(shù)、狀態(tài)積壓在棧上,最終耗盡棧空間。 一個解決的辦法是從算法上解決,把遞歸算法改良成只依賴于少...
摘要:執(zhí)行完了,銷毀調(diào)用棧中自己的記錄,依次銷毀和的調(diào)用幀,最后完成整個流程。尾遞歸定義先來看一下遞歸,當(dāng)一個函數(shù)調(diào)用自身,就叫做遞歸。 尾調(diào)用 1. 定義 尾調(diào)用是函數(shù)式編程中一個很重要的概念,當(dāng)一個函數(shù)執(zhí)行時的最后一個步驟是返回另一個函數(shù)的調(diào)用,這就叫做尾調(diào)用。 注意這里函數(shù)的調(diào)用方式是無所謂的,以下方式均可: 函數(shù)調(diào)用: func(···) 方法調(diào)用: obj.meth...
摘要:算法子節(jié)點(diǎn)比較這部分代碼比較多,先說說原理后面再貼代碼。循環(huán)結(jié)束的標(biāo)志就是舊子節(jié)點(diǎn)數(shù)組或新子節(jié)點(diǎn)數(shù)組遍歷完,即。第二步尾尾比較。第三步頭尾比較。第四步尾頭比較。節(jié)點(diǎn)確認(rèn)后,真實序列為,未確認(rèn)序列為第五次是均不相似,直接插入到未確認(rèn)序列頭部。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準(zhǔn)備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法...
閱讀 529·2023-04-25 14:26
閱讀 1285·2021-11-25 09:43
閱讀 3476·2021-09-22 15:25
閱讀 1447·2019-08-30 15:54
閱讀 520·2019-08-30 12:57
閱讀 765·2019-08-29 17:24
閱讀 3166·2019-08-28 18:13
閱讀 2672·2019-08-28 17:52