本章內容銜接上一章 數據結構與算法:二分查找javascript
兩種基本數據結構:java
數組node
數組降維
、數組去重
- 如何將問題分紅基線條件
和遞歸條件
- 分而治之
策略解決棘手問題git
- 調用棧(call stack)
- 遞歸調用棧github
有序元素列表
。 - 冒泡排序
- 選擇排序
- 插入排序
- 希爾排序
- 歸併排序
- 快速排序
- 堆排序
- 計數排序
- 桶排序
- 基數排序算法
須要將數據存儲到內存時,你請求計算機提供存儲空間,計算機給你一個存儲地址。須要存
儲多項數據時,有兩種基本方式——數組和鏈表。但它們並不是都適用於全部的情形,所以知道它
們的差異很重要
給出:let arr = [[1, 2, 3], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10, 0]; 需求:降維、去重、排序 作法:Array.from(new Set(arr.flat(Infinity).sort((a, b) => a - b))) 解析以下: 0. arr.flat(Infinity) //直接降維值一維數組。 1. sort //排序就不說了。 2. new Set() //達到去重效果 3. Array.from(上一步輸出的結果) //將上一步結果轉換爲數組
遞歸(recursion):程序調用自身的編程技巧。shell
遞歸知足2個條件:編程
遞歸就是指在定義一個概念和過程時,又用到了自己。
哲學的將, 遞歸的妙用就在,若是一個過程當中又包含自身,那麼這個過程就能夠無窮地展開,不會在有窮的步驟後中止。可是描述這個過程只須要有窮的指令。以有窮表現無窮。
在數學與計算機科學中,是指在函數的定義中使用函數自身的方法。遞歸一詞還較經常使用於描述以自類似方法重複事物的過程。例如,當兩面鏡子相互之間近似平行時,鏡中嵌套的圖像是以無限遞歸的形式出現的。也能夠理解爲自我複製的過程。
另外多提一句,遞歸
和lambda 演算
是兩個與圖靈機
等價的計算機理論模型,感興趣的讀者能夠去進一步研究,這裏不贅述。segmentfault
因爲遞歸函數調用本身,編寫這樣的函數時很容易出錯,致使無限循環。數組
例:編寫這樣倒計時的函數。
5...4...3...2...1
爲此,你能夠用遞歸的方式編寫:
const countdown = (i) => { console.log(i) // base case 基準條件 if (i <= 0){ return null } // 隱藏的else是 遞歸條件 countdown(i-1) return null } countdown(5)
編寫遞歸函數時,必須告訴它什麼時候中止遞歸。正由於如此,每一個遞歸函數都有兩部分:基線
條件(base case)和遞歸條件(recursive case)。遞歸條件指的是函數調用本身,而基線條件則
指的是函數再也不調用本身,從而避免造成無限循環。
能夠去掉基準條件執行下代碼:
const countdown = (i) => { console.log(i) // base case 基準條件 // if (i <= 0){ // return null // } // 隱藏的else是 遞歸條件 countdown(i-1) return null } countdown(5)
由於無限循環致使Maximum call stack size exceeded error
n! = n (n-1) (n-2) ... 1(n>0)
// 階乘 const fact = (x) => { if(x === 1) { return 1 } return x * fact(x - 1) } console.log(fact(5))
斐波那契數列能夠定義爲如下序列:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …
能夠看到,該序列是由前兩項數值相加而成的。這個數列的歷史很是悠久,至少能夠追溯 到公元700年。它以意大利數學家列奧納多·斐波那契(Leornardo Fibonacci)的名字命 名,斐波那契在1202年使用這個數列描述理想狀態下兔子的增加。
這是一個簡單的遞歸函數,你可使用它來生成數列中指定序號的數值
這個函數的問題在於它的執行效率很是低
有太多值在遞歸調用中被從新計算。若是編譯器能夠將已經計算的值記錄下來,函
數的執行效率就不會如此差。咱們可使用動態規劃
的技巧來設計一個效率更高的算法。
動態規劃的本質其實就是兩點:
根據上面兩點,咱們的斐波那契數列的動態規劃思路:
樹的最大深度:該題目來自 Leetcode,題目須要求出一顆二叉樹的最大深度
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @return {number} */ var maxDepth = function(root) { if(!root) return 0 return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1 };
對於該遞歸函數能夠這樣理解:一旦沒有找到節點就會返回 0,每彈出一次遞歸函數就會加一,樹有三層就會獲得 3。
可是遞歸真的很慢
咱們能夠寫一個函數 用以遞歸的快速計算
// memoize 全局函數:用以階乘,斐波那契數組等遞歸調用的快速計算 // useage: const memoizeFibonacci = memoize(fibonacci); memoizeFibonacci(45) export function memoize(fn) { const cache = {}; return function () { const key = JSON.stringify(arguments); var value = cache[key]; if (!value) { value = [fn.apply(this, arguments)]; // 放在一個數組中,方便應對undefined,null等異常狀況 cache[key] = value; } return value[0]; } }
Stack Overflow上說的一句話:「若是使用循環,程序的性能可能更高;若是使用遞歸,程序可能
更容易理解。如何選擇要看什麼對你來講更重要。」 Recursion or Iteration?
棧是一個線性結構,在計算機中是一個至關常見的數據結構。
棧的特色是隻能在某一端添加或刪除數據,遵循先進後出的原則
每種數據結構均可以用不少種方式來實現,其實能夠把棧當作是數組的一個子集,因此這裏使用數組來實現
arr = [2,3,6,5,33,7,23] def bubbleSort(arr): for i in range(1, len(arr)): for j in range(0, len(arr)-i): if arr[j] > arr[j+i]: arr[j],arr[j + i] = arr[j + i], arr[j] return arr print(bubbleSort(arr))
arr = [2,3,6,5,33,7,23] def selectionSort(arr): for i in range(len(arr) - 1): # 記錄最小的索引 minIndex = i for j in range(i + 1, len(arr)): if arr[j] < arr[minIndex]: minIndex = j # i 不是最小數時, 將i 和最小數進行交換 if i != minIndex: arr[i], arr[minIndex] = arr[minIndex], arr[i] return arr print(selectionSort(arr))
arr = [2,3,6,5,33,7,23] def insertionSort(arr): for i in range(len(arr)): preIndex = i-1 current = arr[i] while preIndex >= 0 and arr[preIndex] > current: arr[preIndex+1] = arr[preIndex] preIndex-=1 arr[preIndex+1] = current return arr print(insertionSort(arr))
arr = [2,3,6,5,33,7,23] def shellSort(arr): import math gap = 1 while(gap < len(arr)/3): gap = gap*3 + 1 while gap > 0: for i in range(gap, len(arr)): temp = arr[i] j = i - gap while j >= 0 and arr[j] >temp: arr[j+gap] = arr[j] j-=gap arr[j+gap] = temp gap = math.floor(gap/3) return arr print(shellSort(arr))
下一篇文章 數據結構與算法:二叉樹算法
JS-Sorting-Algorithm
javascript描述數據結構與算法(改自imooc)
算法圖解
常見算法js實現
javascript-algorithms
排序算法總結