算法課筆記系列(一)—— 分治算法

首先必須強調的是,我是個算法渣,多少年了~~還是渣/(ㄒoㄒ)/~~

這學期在上英文算法課,機緣巧合選了英文,覺得老師講得還不錯,所以沒換到中文。想要通過這樣總結一下加深算法理解,考試時也方便複習。

第一次課是對學習算法課需要的數學基礎知識的複習,如集合以及集合的操作,函數,關係等,和一些數學證明方法的介紹,包括通過構造證明,通過對照證明(舉反例,找矛盾),通過案例證明(可以理解爲分情況討論證明同一個結論對任一情況都成立),通過數學歸納法證明(包含最小反例法則,數學歸納的強法則)。

第二次課是接觸算法必須的算法複雜度分析,包括時間和空間上的複雜度分析。通過列舉了幾個算法實際案例進行的分析,包括兩種搜索方法(線性搜索,二分搜索),一個合併算法(將兩個已經排好序的列表合併)和三種排序算法(選擇排序,插入排序和合並排序)。

                                        

 第一個詳細講的算法是分治算法,該算法主要用於解決這樣條件下的問題:

(1)      可以被分解成若干個相同的更小的子問題,即該問題具有最優子結構性質;分解到一定的程度就會很容易解決;

(2)      可以循環解決這些子問題;

(3)      最後可以合適的將子問題的解合併爲該問題的解;

(4)      該問題分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題

實際問題就是逐一地解決這三個步驟:在將問題分解成子問題;在遞歸的最後一步,當問題變得足夠小的時候,可以被直接解決了;以及將子問題的答案合併。

使用分治算法的經典例子如下:

(一)  乘法運算

(二)  Merge排序

(三)  求中位數

(四)  矩陣的乘法

先就乘法操作進行一下推導。

(一)  乘法操作

該算法是根據高斯的一個發現,將兩個複數的乘法

                 

原本的四個乘法操作現在將其轉化爲三個,

                 

簡單看來,認爲減少的複雜度並不多。但是當應用到迭代中,會發現可以大大減小複雜度。

         對這個的證明可以將其從複數一般化到整型的乘法。假設x和y是兩個n位的整數,爲了方便假設n都是2的冪。由以上條件,我們可以將x和y轉化爲如下形式:

                  

這樣一來,x和y的乘積可以表示爲:


通過轉化後的式子來計算xy,加法操作和這裏的2的冪都是線性的複雜度,因爲對2求冪就是一個左移的位操作。現在,乘法操作就變成了對四個n/2位的數進行乘法操作的迭代(子問題是原來大小的一半),然後在O(n)時間內將之前的結果進行整合。這樣,使用master theorem來計算整個過程的複雜度的話就是

                  

計算得到算法的複雜度爲O(n^2).

(備註:master theorem如下:


爲了提升算法的運行效率,只用之前高斯提到的方法。原來的四個乘法操作可以轉化爲三個,

                

                                

這樣的話,使用master theorem來計算整個過程的複雜度的話就是

                

,在每一次迭代中,常量從4變爲3,計算出來複雜度爲

該問題的迭代過程可以通過一棵樹來描述。


在子問題的每一次迭代中,問題的規模就減小一半。在次的迭代中,子問題的規模減小到1,迭代終止。因此,數的高度爲。每一次迭代,問題的分支因子爲3,也就是每次問題被分解爲3個子問題,在第k層問題數目爲3^k,每一個子問題的規模爲在樹的第k層需要的時間爲

                     

在樹的最高層,k=0,則複雜度爲O(n)。在最底層,k=,計算出來爲,可以寫成,大約就是.

使用之前的思路,則這棵迭代數的分支因子爲4,則計算,最後複雜度也需要這麼多。

因此,在分治算法中,子問題的數目可以被解釋爲迭代樹的分支因子(master theorem中的a),每一次問題規模的變化係數爲b(減小一半就是1/2),最後將子問題的所有解合併起來的複雜度中n的冪指數即爲d。

例如,二分查找中,在一個已經排好序的序列z[0,1,…,n-1]中找到數k,首先將k與z[2/n]進行比較,根據結果在決定是在前半部分繼續比較還是後半部分繼續比較。這樣得到的迭代公式爲,可以容易計算出該問題的複雜度爲


最後一部分講了關於Sorting Network的畫法,上課的時候聽得比較模糊。下來整理一下之後,過程如下:

1)首先創建一個Bitonic Sorter

先說Bitonic sequence,中文翻譯爲雙調序列,也就是單調遞增和單調遞減的的序列,也可以循環轉換先單調遞增再單調遞減。

例如:

Half-cleaner是長度爲1的比較網絡,是第i個輸入與第i+n/2個輸入比較(假設n是偶數,i = 1,2,...n/2)

如下圖:

          

這樣得到的雙調序列上半部分是更小的值,下半部分是更大的值。上下兩部分都是雙調的。

然後就可以畫Bitonic Sorter的結構:

下面右圖爲n = 8時的Bitonic Sorter

              


2)第二步構造一個Merger

Merger與Half-cleaner是有區別的,Merger[n]是將兩個單調的輸入序列轉換成..bn>, 而Half-CLeaner則是將轉換成。其區別如下圖:

             

於是構建的Merger如下:

                                

3)最後一步就是構造Sorter

                                

下面給出n=8和n=16時的sorting network:

n = 8:

                  

n = 16:


 

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