什麼是算法分析
當咱們說算法分析的時候咱們在說什麼?(狹義的技術層面的定義):
算法分析指的是:
對算法在運行時間和存儲空間這兩種資源的利用效率進行研究。
即時間效率和空間效率。
時間效率指算法運行有多快;
空間效率指算法運行時須要多少額外的存儲空間。
(時間效率也叫時間複雜度;空間效率也叫空間複雜度。)
在計算機時代早期,時間和空間這兩種資源都是及其昂貴的。但通過半個多世紀的發展,計算機的速度和存儲容量都已經提高了好幾個數量級。
如今空間效率已經不是咱們關注的重點了,但時間效率的重要性並無減弱到這種能夠忽略的程度。
因此,當咱們分析一個算法的的時候,咱們只關注它的時間效率。
算法分析通用思路:
當咱們遇到一個算法時,咱們能夠用這樣一個通用的思路去分析它:
1. 輸入規模
首先第一步考慮這個算法的輸入規模是什麼?即輸入參數,再換句話說也就是待解決的問題有多大?
從這裏入手是由於一個顯而易見的規律就是,
無論使用什麼算法,輸入規模越大,運行效率確定會更長。
輸入規模的肯定要根據具體要解決的實際問題的細節來決定,相同的問題不一樣的細節,輸入規模是不同的。好比:一個拼寫檢查的算法,
若是算法關注的是單獨的字符檢查,那麼字符的數量就是輸入規模的大小;
若是算法關注的是詞組搭配的檢查,那麼這個輸入規模就要比單獨的字符檢查的輸入規模要小,這裏輸入規模就是詞的數量了。
2. 運行時間的度量單位
接下來第二步考慮這個算法的運行時間,即這個算法運行地快慢。
咱們能夠簡單地用計時的方法,即某個算法運行了多少毫秒。
但這個方式有一個缺陷就是在不一樣計算機上,相同算法的運行時間是不同,由於有的電腦快有的電腦慢。
因此有沒有一種度量方法能夠排除這些無關因素?
答案是確定的,咱們能夠
關注算法執行了多少步,即操做的運行次數。並且爲了簡化問題咱們只需關注最重要的操做步驟,即所謂的基本操做,由於基本操做已經足夠能夠決定這個算法的品質。
好比一個算法一般是最內層的循環中是最費時的操做,那咱們就只須要把它循環了多少次做爲基本操做進行研究。
3. 增加次數
這裏須要延伸的一點是在大規模的輸入狀況下考慮執行次數的增加次數。由於針對小規模的輸入,在運行時間的差異上不太明顯。好比只對100個數字進行排序,無論你用什麼排序算法,時間效率都差很少。只有在輸入規模變大的時候,算法的差別才變得既明顯又重要了起來。
簡單來講,
- 若是一個算法在輸入規模變大時,但運行時間平緩增加,那麼咱們就能夠說它就是一個效率高的算法;
- 而若是一個算法在輸入規模變大時,它的運行時間成指數級增加,那就能夠說這個算法的效率不好。
總而言之就是,
對基本操做的大規模輸入狀況下的變化的研究才更具備深遠意義。
4. 算法的最優、最差和平均效率
當咱們瞭解了輸入規模對算法時間效率的會產生影響,但算法的執行效率卻不只僅只受輸入規模的影響,某些狀況下,
算法的執行效率更取決於輸入參數的細節。
好比:一個簡單的順序查找的算法,在數組裏查找數字 9:
在數組 list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9] 裏查找數字 9 和在相同的輸入規模的另外一個數組 list2 = [9, 1, 2, 3, 4, 5, 6, 7, 8]裏查找數字 9,在數組 list2 的執行效率確定更高。
上面小例子中的兩個數組就體現了兩個極端:輸入最優狀況和輸入最壞狀況。
相對應的,
在輸入最優狀況下的算法就叫最優效率;
在輸入最壞狀況下的算法就叫最差效率;
在這裏有兩個經驗性的規則:
- 最優效率的分析遠遠不如最差效率分析重要(由於最差效率能夠肯定算法運行時間的上界);
- 若是一個算法的最優效率都不能知足咱們的要求,那麼咱們就能夠當即拋棄它。
在現實狀況下,輸入是「隨機」的,既不會是最優輸入也不會是最壞輸入。因此這裏又要引出一個概念,即:平均效率。
首先指出,咱們
毫不能用「最優效率」和「最差效率」的平均數求得平均效率,即使有時間這個平均數和真正的平均效率巧合地一致。
正確的步驟是:咱們要對輸入規模 n 作一些假設。
對於上面的順序查找算法的例子,標準的假設有兩個:
- 輸入裏包含目標數字,那麼算法會成功查找到目標數字,此時,成功查找機率是 p(0 <= p <= 1);
- 對於任意數字 i,匹配發生在列表的第 i 個位置的機率是相同的。
基於這兩個假設求平均效率可得:
- 成功查找到目標的狀況下,對於任意 i,第一次匹配發生在第 i 個位置的機率都是 p/n,此時,算法所作的比較次數是 i;
- 輸入數組裏不包含目標數字,那麼算法不成功查找,比較次數是 n,在這種狀況下,可能性是 (1-p)。
由此,平均效率 C(n) = p(n+1) / 2 + n(1-p)
C(n) = [1 * p/n + 2 * p/n + ... + i * p/n + ... + n * p/n] + n*(1-p)
= p/n[1 + 2 + ... + i + ... + n] + n(1-p)
= p/n * n(n+1)/2 + n(1-p)
= p(n+1) / 2 + n(1-p)
由此可知,
- 若是 p = 1,也就是說成功率是 100%,查找必定能成功,代入公式可得 (n+1)/2,即大約要查找數組中一半的元素;
- 若是 p = 0,也就是說成功率是 0%,查找一定失敗,代入公式可得 n,即算法會對全部元素所有查找一遍。
從這個例子能夠發現,平均效率的研究要比最差效率和最優效率的研究困難不少:
咱們要將輸入規模 n 劃分爲幾種類型,對於同類型的輸入,使得算法的執行次數是相同的。
結束:
算法是計算機科學的基礎,之後會繼續更新算法相關的隨筆,對算法感興趣的朋友歡迎關注本博客,也歡迎你們留言討論。
咱們正處於大數據時代,對數據處理感興趣的朋友歡迎查看另外一個系列隨筆: