数据结构与算法---笔记
第一章
1.1 計算
計算機只是我們的工具(手段),我們研究的對象是計算。
計算 = 信息處理
借助某種工具,遵照一定規則,以明確而機械的形式進行。
機器模型 = 計算機 = 信息處理工具
所謂算法,即特定計算模型下,旨在解決特定問題的指令序列
- 輸入,待處理的信息(問題)
- 輸出,經處理的信息(答案)
- 正確性,的確可以解決指定的問題
- 確定性,任一算法都可以描述為一個由基本操作組成的序列
- 可行性,每一基本操作都可實現,且在常數時間內完成
- 有窮性,對于任何輸入,經有窮次基本操作,都可以得到輸出
好算法的定義
- 正確,對于輸入有正確的輸出
- 健壯,對于不合法的操作,可以恢復程序的正常執行
- 可讀,結構化+準確命名+注釋+ ···
- 效率,速度盡可能快,存儲空間盡可能少
程序 = 數據結構 + 算法
要改進或者優化某個算法,我們需要先知道這個算法的效率。
算法分析
- 正確性,算法功能與問題要求是否一致
- 成本,運行時間+所需存儲空間
通常我們對一個算法的度量值的大小都取這個度量規模的最壞情況。
對于特定問題+不同算法,我們該如何判斷其優劣呢?考察以下兩種模型
- TM模型(圖靈機)。
- RAM模型(匯編)。
我們度量的單位為CPU的執行次數,算法在必要的時候需要復位。
大 O 記號
n為問題規模。
常系數可忽略:
O(f(n))=O(c?f(n))O(f(n))=O(c?f(n))低次項可忽略: O(na+nb)=O(na),a>b>0O(na+nb)=O(na),a>b>0
其他記號:
- Big Ω,最大下界。
- Big θ ,折中。
O的等級:
- 常數,O(1)
- 對數,O(logn),以2為底數
- 多項式,O(n^c)
- 線性復雜度,O(n)
- 指數復雜度,O(2^n)
算法效率從O(2^n)到O(n^c)是一個難點。通常情況下,我們想找出一個效率從指數到多項式的算法是非常難的。這是一個分水嶺。
定理:2-Subset is NP-complete。解釋:就目前的計算模型而言,不存在可在多項式時間內回答此問題的算法。
NP問題就是一個冪集問題,效率為O(2^n)。
算法分析
兩個主要任務 = 正確性( 不變性*單調性 ) + 復雜度。
C++等高級語言的基本指令,均等效于RAM的基本指令;在漸進意義下,二者大體相當。
復雜度分析的主要方法:
- 迭代:級數求和
- 算術級數:與末項的平方同階
- 冪方級數:比冪次高出一階
- 幾何級數:與末項同階
- 收斂級數:常數 O(1)(某種情況下是有意義的,比如迭代的去投擲一枚硬幣,直到出現正面)
- 調和級數:O(logn)
- 對數級數:O(nlogn)
- …(有一本書叫做《具體數學》)
- 遞歸:遞歸跟蹤 + 遞推方程
- 猜想 + 驗證
迭代與遞歸
迭代乃人工,遞歸方神通。
從效率上講,迭代效率比遞歸效率要來的高。我們需要學習的是從遞歸到迭代的一個過程。
凡治眾如治寡,分數是也。
對于一個問題,分成一系列子問題。通過求解子問題進而得出這個問題的解。
減而治之與分而治之。
動態規劃
第一個例子:斐波那契數列
遞歸版本的fib和迭代版的fib的效率相差巨大(原因重新計算已經被計算過的fib數)。
//遞歸版 int fib(int n){return (2>n)? n : fib(n-1) + fib(n-2); }很明顯這是求解一個冪集問題,這段代碼時間復雜度是2的n次方,空間復雜度是O(n)。
改進1:記憶版本(制表)
//迭代 int arr[] = new int[n+1]; arr[1] = 1; arr[2] = 1; for(int i=3;i<n;i++){arr[i] = arr[i-1]+arr[i-2]; } return arr[n];以上時間復雜度和空間復雜度都是O(n)。
改進2:動態規劃(自底而上)
//迭代 int f=0,g=1; while(0<n--){g = g+f;f = g-f; } return g;時間復雜度是O(n),空間復雜度是O(1)。
第二個例子:LCS序列
遞歸版(算法步驟):
對于序列 A[0, n] 和 B[0, m] 無非三種情況
明顯是一個冪集問題,所以時間復雜度為O(2^n),空間復雜度為O(n)。
由遞歸分析,我們得出一個結論,重復元素多次計算,所以我們可以改進。
迭代版(制表):
顯然時間復雜度和空間復雜度都為O(n*m)。
總結
以上是生活随笔為你收集整理的数据结构与算法---笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对象导论---JAVA编程思想
- 下一篇: 互联网日报 | 2月4日 星期四 | 阿