【算法學習筆記一】算法基礎

在學習算法的過程中始終離不開三個問題:

1.如何找到一個有效的算法去解決問題;

2.對於解決同樣的問題,如何比較不同的算法;

3.如何判斷算法的優點。

 基本概念

一.算法定義

算法就是一個由有限的指令集組成的過程。從可能的輸入集中給這個過程一個輸入,如果系統地執行該指令集,那麼對於這個特定地輸入,當輸出存在時,就能得到輸出;當沒有輸出時,就什麼結果也得不到。可能地輸入集是指能讓該算法給出能讓該算法給出一個輸出的所有輸入。如果對於一個特定的輸入就一個輸出,那麼就說該算法能用於這一輸入,執行該算法能夠得到相應的輸出。

我們要求算法對於每一個輸入能停下來,這意味着每一條指令只需要有限的時間,同時每一個輸入的長度是有限的,同時對於一個合法輸入所對應的輸出是唯一的。

數字計算機出現後,對於可解問題研究的要求越來越多。起初人們滿足於一個簡單的程序能夠在它需要的時間內求解一個特定的問題,而不考慮資源量。之後由於有限的可用資源和開發複雜算法的要求,提出了對儘可能少使用資源的有效算法的需求。這導致在計算領域出現了一個成爲計算複雜性的新領域。

二.時間複雜性

在計算複雜性領域中,研究的主要目的是一個算法所需要的時間和空間,即當給合法輸入時,爲了得到輸出,該算法所需要的時間和空間。在分析算法運行時間,通常將該算法和解決同一問題甚至不同問題的算法相比較,這樣估計時間是相對的而不是絕對的;其次,無論科技如何進步,對算法運行時間的測度始終成立;最後,不是主要關心小規模輸入量的情況,最關心的是在最大輸入的實例時,算法的運行情況。

1.元計算

對任何計算步驟,他的代價總是以一個時間常量爲上界,而不管輸入數據或執行的算法,我們稱該計算步驟爲“元計算”。例如取兩個整數相加的運算,不管使用何種算法,我們規定它的運算對象的大小時固定的,這一運算時間是常數。

2.O符號

f(n)g(n)是從自然數集到非負實數集的兩個函數,如果存在一個自然數n_0和一個常數c>0使得\forall n\geq{n_0},f(n) \leq cg(n),則稱f(n)O(g(n))。因此如果\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}存在,那麼\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}\neq \infty蘊含着f(n)=O(g(n))。(希望找到最低上界,只考慮最高項,不考慮低階項和非1的係數)。

O符號也可作爲一個簡化工具用在等式中。例f(n)=5n^3+7n^2-2n+13\rightarrow f(n)=5n^3+O(n^2)

3.\large \textbf{\Omiga}\large $\pmb{\Omega }$\large $\textbf{\Omega }$符號

f(n)g(n)是從自然數集到非負實數集的兩個函數,如果存在一個自然數n_0和一個常數c>0使得\forall n\geq{n_0},f(n) \geq cg(n),則稱f(n)\Omega (g(n))。因此如果\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}存在,那麼\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}\neq 0蘊含着f(n)=\Omega (g(n))。(希望找到最高下界)

f(n)=\Omega (g(n)),則g(n)=O(f(n))

4.\large \Theta符號

f(n)g(n)是從自然數集到非負實數集的兩個函數,如果存在一個自然數n_0和兩個正常數,使得\forall n\geq{n_0},c_1g(n) \leq f(n) \leq c_2g(n),則稱f(n)\Theta (g(n))。因此如果\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}存在,那麼\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}= c蘊含着f(n)=\Theta (g(n)),其中c必須是一個大於0的常數。

這一符號是用來表示算法的精確階的,它蘊涵着在算法的運行時間上有確切界限。

推論:f(n)=\Theta (g(n)),當且僅當f(n)=O(g(n))f(n)=\Omega (g(n))

任意常函數是O(1),\Omega(1),\Theta(1)

如,f(n)=5n^2-10n+55,則f(n)=\Theta (n^2)f(n)=logn^k,則f(n)=\Theta (logn)

f(n)f(n+1)的關係取決於具體的f(n)是什麼。當f(n)=2^n,f(n+1)=2^{n+1}=2f(n)=\Theta(f(n));而當f(n)=n!,f(n+1)=(n+1)!,f(n)=O(f(n+1))\neq \Omega(f(n+1))

logn!=\sum_{j=1}^{n}logj=\Theta(nlogn)\sum_{j=1}^{n}\frac{n}{j}=\Theta(nlogn)

 5.o符號

f(n)g(n)是從自然數集到非負實數集的兩個函數,如果存在一個自然數n_0和對每一個一個常數c>0使得\forall n\geq{n_0},f(n) \textless cg(n),則稱f(n)o(g(n))。因此如果\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}存在,那麼\lim_{n\rightarrow \infty }\frac{f(n)}{g(n)}=0蘊含着f(n)=o(g(n))

f(n)=o(g(n)),當且僅當f(n)=O(g(n)),g(n)\neq O(f(n));例如nlogn是o(n^2)的等價於nlogn是O(g(n)),但n^2不是O(nlogn)的。

1\prec loglogn\prec logn\prec \sqrt{n}\prec n^\frac{3}{4}\prec n\prec nlogn\prec n^2\prec 2^n\prec n!\prec 2^{n^2}

 三.空間複雜性

爲了求解問題的實例而執行的計算步驟所需要的內存空間數目,它不包括分配用來存儲輸入的空間,換句話說,僅僅是算法需要的工作空間。算法的空間複雜性不可能超過運行時間的複雜性,因爲寫入每一個內存單元都至少需要一定的時間,如果用T(n)和S(n)分別代表算法的時間複雜性和空間複雜性,則有S(n)=O(T(n))。

四.最優算法

一般來說,如果可以證明任何一個求解問題\Pi的算法必定是\Omega (f(n)),那麼把在O (f(n))時間內求解問題\Pi的任何算法都稱爲問題\Pi的最優算法。

五.估算迭代次數

1.計算迭代次數

運行時間常常和while循環及類似結構的執行次數成正比。這樣,計算迭代次數將很好得表明算法得運行時間。這種情況適用於很多算法,包括搜索、排序、矩陣乘法等。

2.計算基本運算得頻度

如果算法中的一個元運算具有最高頻度,所有其他元運算頻度均在它的頻度的常數倍內,則稱這個元運算爲基本運算。

3.使用遞推關係

六.最壞情況和平均情況分析

在時間複雜性的最壞情況分析中,在所有大小爲n的輸入中選擇代價最大的;在平均情況分析中,運行時間是指在所有大小爲n的輸入的平均時間。

七.輸入大小(Input Size)

一個算法執行性能的測度通常是它的輸入的大小、順序和分佈的函數,其中最重要的是輸入的大小。輸入的大小作爲一個數量,不是輸入的精確測度,它解釋爲從屬於已設計或將要設計的算法的問題。一些常用輸入大小的測度如下:

在排序和搜索問題中,用數組或表中元素的數目作爲輸入大小;

在圖的算法中,輸入大小通常指圖中的邊喝頂點的數目,或二者皆有;

在計算幾何中,算法的輸入大小通常用點、頂點、邊、線段或多邊形等的個數來表示;

在矩陣運算中,輸入大小通常是輸入矩陣的維數;

在數論算法和密碼學中,通常選擇輸入的比特數來表示它的長度。當一個字由固定的比特數組成時,一個數字的字數也可以選來表示輸入的長度。

評價算法優劣:1)線性時間算法;2)平方/二階時間算法;3)對數時間算法;4)指數時間算法;

例:

    for i=1 to n
        for j=1 to n
            c[i,j]=a[i,j]+b[i,j]
        endfor
    endfor

將兩個nxn的矩陣相加的算法要執行\large n^2次加法,看上去是平方的關係,而實際上與輸入的大小(矩陣維數)關係卻是線性的,即線性時間算法;

    for i=2 to sqrt(n)
        if n%i=0
            輸出n爲合數
    endfor
    輸出n爲素數

 測試素數性的蠻力算法,它的時間複雜性爲O(\large \sqrt{n}),由於這是個數論問題,所以輸入大小用n的二進制形式中的比特數來測度,n的二進制的比特數爲k=logn,則時間複雜性可寫作O(\large 2^{\frac{logn}{2}}),則算法實質上是一個指數算法。

#Algorithm FIRST
    sum←0
    for j←1 to n
        sum←sum+A[j]
    end for
    return sum

#Algorithm SECOND
    sum←0
    for j←1 to n
        sum←sum+j
    end for
    return sum

第一個算法是線性時間算法,數組A的規模爲輸入規模,即\large \Theta(n);第二個是指數時間算法,數論問題選擇輸入的比特數來表示它的長度,比特數k=logn,\large \Theta(n)=\large \Theta(\large 2^{logn})。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章