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