算法導論公開課筆記(一)算法分析與設計

算法分析

算法分析是關于計算機程序性能和資源利用的理論研究;性能研究主要是學習如何讓算法或者應用程序 運行的更快; 資源利用主要指的是諸如通信、存儲器(無論是RAM Memory還是disk Memory)等的使用情況。
算法是關注性能問題的學科,因此這部分內容很重要。

設想,如果你在一家公司從事軟件開發(fā)工程的從事編程工作,有那些比性能更重要的東西?

  • 代碼簡潔
  • 可維護性
  • 開發(fā)的時間成本
  • 崩潰率
  • 安全性
  • 用戶友好

佷明顯,真實的軟件開發(fā)場景中有諸多的方面都比性能重要。但是算法是關注性能的科學,如果算法和性能都不重要,我們?yōu)槭裁催€要學習這樣一個課程。

  1. 性能的好壞可以決定解決方案可行性。

  2. 算法是一種描述程序行為的語言,業(yè)已廣泛應用于計算機科學領域,且已經被所有的實踐者所采用的理論語言,它是思考程序最為簡潔的一種方式。
    性能為什么處于程序開發(fā)中的最底層。這里有一個很好的類比,性能在程序中扮演的角色就如同經濟中的貨幣一樣,貨幣可以購買人基本生活中所需的一切東西,如,食物,衣服,房子和水。可能水對你的生命而言比錢重要,但是你能買下這些商品的前提是有錢。同樣,性能是確保良好用戶體驗的前提。

  3. 追求運行速度,是算法研究最讓人興奮的地方。

排序問題

通過排序問題,進行算法分析。

插入排序

插入排序的偽代碼如下:

INSERTION-SORT(A)
1  for j=2 to A.length
2    key=A[j]
3    //將A[j]插入到有序的子數組A[1..j-1]。
4    i=j-1
5    while i>0 and A[i]>key
6      A[i+1]=A[i]
7      i=i-1
8    A[i+1]=key

Java 版本代碼實現如下:

    void insertSort(int[] arr){
        if(arr==null||arr.length<2) return;
        for(int i=1;i<arr.length;i++){
            int key=arr[i];
            int j=i-1;
            while (j>=0 && arr[j]>key){
                arr[j+1]=arr[j];
                j--;
            }
            arr[j+1]=key;
        }
    }

運行時間分析

運行時間依賴于下面的因素

  • 輸入項
  • 輸入項的規(guī)模

分析運行時間的方式

  1. 最壞情況-Worst-case(usually)
    T(n) = max time on any input of size n
  2. 平均情況-Average-Case(somtimes)
    T(n) =excepted time all input size n
    前提是,需要一個有關輸入統(tǒng)計分布的假設
    每種輸入的運行時間乘以該輸入出現的概率進行加權平均所得到的時間,就是期望運行時間
  3. 最好情況Best_Case(假象)
    假設,用已經做好排序的序列檢驗"低速"算法,得到的運行時間可以的到最好情況。

最壞情況的運行時間分析:

  • 依賴使用的計算機、
    相對運行時間(在相同計算機上運行)
    絕對運行時間(在不同計算機上運行)

漸進分析(Asymptotic Analysis)

  1. 忽略那些依賴于機器的常量
  2. 當n趨近于∞過程中,忽略機器實際的運行時間,而是T(n)的增長
    漸進符號
  • Θ 標記
    漸進緊確界
    舍棄低階項,并忽略前面的常數因子
    例如,如果公式為3n3+90n2-5n+6046=Θ(n3)
    當n->∞時Θ(n2)的算法總是能戰(zhàn)勝一個Θ(n3)的算法,其他項不會動搖這個結果,假設在一臺性能好的機器上運行Θ(n3)的算法,在一臺性能差的機器上運行Θ(n2)的算法,只要n足夠大,Θ(n2)的算法總是能戰(zhàn)勝一個Θ(n3)的算法,這個結論依然成立,這就是漸進符號的偉大之處(它能一舉滿足我們對相對和絕對速度的雙重比較要求)。
image.png

從工程視角來看有時臨界值n0的過大,大到計算機無法運行,這就是我們?yōu)槭裁磿Φ退俚乃惴^興趣的原因,有一些算法盡管用漸進的觀點來看,他們有可能比較慢,但是在合理規(guī)模輸入的情況下運行的更快,所以我們要從數學的理解和工程的直覺之間尋找平衡,這樣我們才能寫出更好的程序。僅僅會做算法分析,并不能是你成為一個編程高手。
老司機講段子,“如果你想成為編程高手,你可以在兩年中每天編程;如果你想成為世界級的編程高手,你可以每天編程,然后上一門算法課”。

插入排序的算法分析
內存引用計數。
最壞情況:T(n)=

image.png
  • O 標記
    Θ 標記漸進的給出了一個函數的上界和下界,當只有一個漸進上界時,使用O 記號。

  • Ω 標記
    正如O標記提供了一個函數的漸近上界,Ω 記號提供了漸近下界。

算法設計

我們可以選擇使用的算法設計技術有很多。插入排序使用了增量方法:在排序子數組A[1..j-1]后,將單個元素A[j] 插入子數組的適當位置,產生排序好的子數組A[1..j]。

下面考查一種“分治法”的設計方法,我們將用分治法來設計一種排序算法,該算法的最壞情況的運行時間比插入排序要少得多。分鐘算法的優(yōu)點之一是,通過算法分析技術很容易確定其運行時間。

分治法

早在中國漢代就有使用。中國歷史版本"分治法"之推恩令

推恩令是漢武帝為了鞏固中央集權而頒布的一項重要政令。這項政令要求諸侯王將自己的封地分給自己的子弟。后來根據這項政令,諸侯國被越分越小,漢武帝再趁機削弱其勢力。

許多算法結構上的遞歸的:為了解決一個給定的問題,算法一次或多次的遞歸調用其自身以解決相關的若干子問題。將原問題分解為幾個規(guī)模較小但是類似原問題的子問題,遞歸地求解這些子問題,然后再合并這些子問題的解來建立原問題的解。
分治模式在每層遞歸時的三個步驟:

  1. 分解
  2. 解決
  3. 合并

歸并排序

  1. 分解
    分解待排序的n個元素的序列成n/2個元素的兩個子序列。
  2. 解決
    使用歸并排序遞歸的排序兩個子序列。
  3. 合并
    合并兩個已經排序的的子序列以產生一排序的答案。

插入排序的偽代碼如下:

MERGE-SORT(A)
1  for j=2 to A.length
2    key=A[j]
3    //將A[j]插入到有序的子數組A[1..j-1]。
4    i=j-1
5    while i>0 and A[i]>key
6      A[i+1]=A[i]
7      i=i-1
8    A[i+1]=key

Java 版本代碼實現如下:

    /**
     * 前提[l,mid]有序并且(mid,r]有序 目標:通過
     * 
     * @param src
     *            i:{6,9,10,2,8,11} out:[2,6,8,9,10,11]
     * @param tmp
     *            臨時存放順序的數組
     * @param left
     * @param mid
     * @param right
     */
    public static void mergeArray(int[] src, int[] tmp, int left, int mid,
            int right) {
        int tmpIndex = left;
        int leftStart = left;
        int rightStart = mid + 1;
        while (tmpIndex <= right) {// 臨時數組為填滿表明合并未完成
            if (leftStart <= mid && rightStart <= right) {// 這種情況是兩個subarray都未合并結束
                tmp[tmpIndex++] = src[leftStart] < src[rightStart] ? src[leftStart++]
                        : src[rightStart++];// 條件成立者賦值給臨時數組后索引右移(+1)
            } else if (leftStart <= mid) {// 這種情況證明右側的subArray合并結束
                tmp[tmpIndex++] = src[leftStart++];
            } else if (rightStart <= right) {// 這種情況表明左側的subArray合并結束
                tmp[tmpIndex++] = src[rightStart++];
            }
        }// 臨時數組保存了 [left,right]的合并結果

        System.arraycopy(tmp, left, src, left, right - left + 1);
    }

    
    /**
     * 二路歸并實現
     * @param src
     * @param tmp
     * @param left
     * @param right
     */
    public static void mergeSort(int[] src, int[] tmp, int left, int right) {
        if (left >= right)
            return;

        int mid = (right + left) / 2;
        
        mergeSort(src, tmp, left, mid);
        mergeSort(src, tmp, mid + 1, right);
        mergeArray(src, tmp, left, mid, right);

    }

歸并排序的時間復雜度為 Θ(nlgn),隨著規(guī)模n的增大,歸并排序的運行時間達到了漸進最優(yōu),但是歸并排序的一個缺點是需要開辟一個同等長度的內存空間才能正常運行。

以上,謝謝閱讀,希望你有所收獲!

算法導論公開課筆記(一)算法分析與設計
算法導論公開課筆記(二)快速排序和隨機化算法
算法導論公開課筆記(三)線性時間排序
算法導論公開課筆記(四)順序統(tǒng)計、中值
動態(tài)規(guī)劃算法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • Chapter 2 插入排序 線性查找 選擇算法 歸并排序算法 二分查找算法 冒泡排序 插入排序 循環(huán)不...
    只是無情緒閱讀 1,467評論 0 1
  • 一. 寫在前面 要學習算法,“排序”是一個回避不了的重要話題,在分析完并查集算法和常用數據結構之后,今天我們終于可...
    Leesper閱讀 2,544評論 0 40
  • 原博客 1.選擇排序(Selection Sort): 選擇最小元素,移動到首位置。 (1)算法描述和實現: 首先...
    Gitfan閱讀 550評論 0 0
  • 1 初級排序算法 排序算法關注的主要是重新排列數組元素,其中每個元素都有一個主鍵。排序算法是將所有元素主鍵按某種方...
    深度沉迷學習閱讀 1,423評論 0 1
  • 本文轉自公眾號 「程序員私房菜 」 一直有寫一篇關于排序算法文章的打算,直到我看到了這一篇,我放棄了自己寫的打算,...
    KEEPINUP閱讀 2,460評論 4 15