1. 程式人生 > >演算法設計與分析之分治思想

演算法設計與分析之分治思想

演算法基礎

問題求解的關鍵

建模:
    對輸入引數和解給出形式化或半形式化的描述

設計演算法:
    採用什麼演算法設計技術
    正確性--是否對所有的例項都得到正確的解

分析演算法--效率

演算法+資料結構=程式

好的演算法

提高求解問題的效率
節省儲存空間

演算法的研究目標

問題->建模並尋找演算法        演算法設計技術
演算法->演算法的評價            演算法分析方法
演算法類-> 問題複雜度估計     問題複雜度分析
問題類-> 能夠求解的邊界     計算複雜性理論

演算法

有限條指令的序列
這個指令序列確定瞭解決某個問題的一系列運算或操作

演算法A解問題P

  • 把問題P的任何勢力作為演算法A的輸入

  • 每步計算是確定性的

  • A能夠在有限步停機輸出該例項的正確的解

演算法時間複雜度:針對指定基本運算,計數演算法所做運算次數

基本運算:比較,加法,乘法,置指標,交換。。。。

輸入規模:輸入串編碼的長度。 比如:陣列元素多少,排程問題的任務個數

演算法基本運算次數可表為輸入規模的函式 
給定問題和基本運算就決定了一個演算法類

演算法的兩種時間複雜度

  • 最壞情況下的時間複雜度W(n)

  • 平均情況下的時間複雜度A(n)

分治策略的基本思想

分治策略
    將原始問題劃分或者歸結為規模較小的子問題
    遞迴或迭代求解每個子問題
    將子問題的解綜合得到原問題的解

注意:
    子問題與原始問題性質完全一樣
    子問題之間可彼此獨立地求解
    遞迴停止時子問題可直接求解

分治演算法的特點:

將元問題歸約為規模小的子問題,子問題與原問題具有相同的性質;
子問題規模足夠小時可直接求解;
演算法可以遞迴也可以迭代實現;
演算法的分析方法:遞推方程

分治演算法設計要點

原問題可以劃分或者歸約為規模較小的子問題
    子問題與原問題具有相同的性質;
    子問題的求解彼此獨立
    劃分時子問題的規模儘可能均衡

子問題規模足夠小時可直接求解
子問題的解綜合得到原問題的解
演算法實現:遞迴或迭代

分治演算法之快速排序

基本思想

    用首元素x作劃分標準,將輸入陣列A劃分成不超過x的元素構成的陣列AL,大於x的元素構成的陣列AR,其中AL,AR從左到右存放在陣列A的位置。

    遞迴地對子問題AL和AR進行排序,直到子問題規模為1時停止

偽碼

    演算法 Quicksort(A,p,r)
    輸入: 陣列A[P..r]
    輸出: 排好序的陣列A

        1. if p<r
        2. then q <- Partition(A,p,r)
        3.      A[p] <-> A[q]
        4.      Quicksort(A,p,q-1)
        5.      Quicksort(A,q+1,r)

    劃分過程:
        Partition(A,p,r)
        1. x ← A[p]
        2. i ← p
        3. j ← r+1
        4. while true do
        5.     repeat j ← j-1
        6.      until A[j] <=x //不超過首元素
        7.      repeat i ← i+1
        8.      until A[i] > x  //比首元素大的
        9.      if i<j
        10.     then A[i] ←→ A[j]
        11.     else return j

時間複雜度

  • 最壞情況: 
    W(n)=W(n-1)+n-1 
    W(1)=0 
    W(n)=n(n-1)/2

  • 最好劃分 
    T(n)=2T(n/2)+n-1 
    T(1)=0 
    T(n)=θ(nlogn)

小結

快速排序演算法

  • 分治策略

  • 子問題劃分時由首元素決定

  • 最壞情況下時間O(n的2次方)

  • 平均情況下時間為O(nlogn)

冪乘演算法及應用

冪乘問題

輸入: a為給定實數,n為自然數 
輸出:a的n次方 
傳統演算法:順序相乘 
a的n次方=(….(((a a)a)a)..)a 
乘法次數:θ(n)

分治演算法——劃分 
0?wx_fmt=png

分治演算法分析 
以乘法作為基本運算

  • 子問題規模,不超過n/2

  • 兩個規模近似n/2的子問題完全一樣,只要計算1次 
    W(n)=W(n/2)+θ(1) 
    W(n)=θ(log n)

冪乘演算法的應用

Fibonacci數列:1,1,2,3,5,8,13,21,…. 
增加F0=0,得到數列:0,1,1,2,3,5,8,13,21…. 
問題:已知F0=0,F1=1,給定n,計算Fn

通常演算法:從F0,F1,….開始,根據遞推公式:F(n)=F(n-1)+F(n-2) 
陸續相加可得Fn,時間複雜度為θ(n)

Fibonacci數的性質 
0?wx_fmt=png

0?wx_fmt=png

演算法: 
令矩陣0?wx_fmt=png ,用乘冪演算法計算0?wx_fmt=png 
時間複雜度:

  • 矩陣乘法次數 T(n)=θ(log n)

  • 每次矩陣乘法需要8次元素相乘

  • 總計元素相乘次數為θ(log n)

改進分治演算法的途徑1:減少子問題數

減少子問題個數的依據

分治演算法的時間複雜度方程

W(n)=a*W(n/b)+d(n)

a:子問題數,n/b:子問題規模, 
d(n):劃分與綜合工作量

當a較大,b較小,d(n)不大時,方程的解: 
0?wx_fmt=png

減少a是降低函式W(n)的階的途徑 
利用子問題的依賴關係,使某些子問題的解通過組合其他字問題的解而得到

例子:矩陣相乘的問題

矩陣乘法的研究及應用

矩陣乘法問題的難度:

  • Coppersmith-Winograd 演算法:0?wx_fmt=png 目前為止最好的上界

  • 目前最好的下界:0?wx_fmt=png 
    應用

  • 科學計算、影象處理、資料探勘等

  • 迴歸、聚類、主成分分析、決策樹等挖掘演算法常涉及大規模矩陣運算

改進途徑小結

  • 適用於:子問題個數多,劃分和綜合工作量不太大,時間複雜度函式 
    0?wx_fmt=png

  • 利用自問題依賴關係,用某些子問題解的代數表示式表示另一些子問題的解,減少獨立計運算元問題個數。

  • 綜合解的工作量不影響W(n)的階。

改進分治演算法的途徑2:增加預處理

例子:平面點對問題

輸入:平面點集P中有n個點,n>1 
輸出:P中的兩個點,其距離最小

蠻力演算法: 
C(n,2)個點對,計算最小距離,O(n的2次方)

分治策略:P劃分為大小相等的PL和PR

演算法偽碼: 
0?wx_fmt=png

演算法分析:

0?wx_fmt=png

增加預處理: 
原演算法: 
在每次劃分時對子問題陣列重新排序

改進演算法:

  1. 在遞迴前對X,Y排序,作為預處理

  2. 劃分時對排序的陣列X,Y進行拆分,得到針對子問題PL的陣列XL,YL及針對子問題PR的陣列XR,YR

    原問題規模為n,拆分的時間為O(n)

改進演算法時間複雜度 
0?wx_fmt=png

改進分治演算法的途徑:小結

依據

W(n)=a*W(n/b)+f(n)

提高演算法效率的方法:

  • 減少子問題個數a: 
    0?wx_fmt=png

  • 增加預處理,減少f(n)

分治演算法典型應用:

選第二大

輸入:n個數的陣列L 
輸出:第二大的數 second

通常演算法:順序比較

  1. 順序比較找到最大max

  2. 從剩下n-1個數中找最大,就是第二大second

    時間複雜度:W(n)=n-1+n-2=2n-3

提高效率的途徑

  • 成為第二大數的條件:僅在與最大數的比較中被淘汰

  • 要確定第二大數,必須找到最大數

  • 在確定最大數的過程中記錄下被最大數直接淘汰的元素

  • 在上述範圍(被最大數直接淘汰的數)內的最大數就是第二大數

  • 設計思想:用空間換時間

錦標賽演算法

  1. 兩兩分組比較,大者進入下一輪,知道剩下1個元素max為止。

  2. 在每次比較中淘汰較小元素,將被淘汰元素記錄在淘汰它的元素的連結串列上

  3. 檢查max的連結串列,從中知道最大元素,即second

偽碼 
演算法 FindSecond 
輸入:n個數的陣列L,輸出:second

  1. k <- n //參與淘汰的元素數

  2. 將k個元素兩兩1組,分成[k/2]組

  3. 每組的2個數比較,找到較大數

  4. 將被淘汰數記入較大數的連結串列 
    =======一輪淘汰結束==============

  5. if k 為奇數 then k <- [k/2]+1

  6. else k <- [k/2]

  7. if k>1 then geto 2 //繼續分組淘汰

  8. max <- 最大數

  9. second <- max 的連結串列中的最大

    例項 
    0?wx_fmt=png

時間複雜度分析

第一階段元素數:n 
比較次數:n-1 
淘汰了n-1個元素

第二階段:元素數[log n] 
比較次數:[log n]-1 
淘汰元素數為[log n]-1

時間複雜度是 
W(n)=n-1+[log n]-1=n+[log n]-2

小結

小結:分治演算法設計

  • 將元問題歸約為子問題:

    • 直接劃分注意儘量均衡

    • 通過計算歸約為特殊的子問題

    • 子問題與原問題具有相同的性質

    • 子問題之間獨立計算

  • 演算法實現:

    • 遞迴或迭代實現

    • 注意遞迴執行的邊界

小結:分治演算法的分析及改進

  • 時間複雜度分析: 

    • 給出關於時間複雜度函式的遞推方程和初始值

    • 求解方程

  • 提高效率的途徑:

  • 減少子問題個數

  • 預處理

小結: 重要的分治演算法

  • 檢索演算法:二分檢索

  • 排序演算法:快速排序、二分歸併排序

  • 選擇演算法: 選最大與選最小、選第二大

  • 快速傅立葉變換FFT演算法

  • 平面點集的凸包

更多關於hadoop,spark和機器學習文章請關注本文公眾號:

640?wx_fmt=jpeg

相關推薦

演算法設計分析分治思想

演算法基礎問題求解的關鍵建模:    對輸入引數和解給出形式化或半形式化的描述 設計演算法:

計算機演算法設計分析遞迴分治策略——二分搜尋技術

遞迴與分治策略 二分搜尋技術   我們所熟知的二分搜尋演算法是運用分治策略的典型例子,針對這個演算法,先給出一個簡單的案例。   目的:給定已排好序的n個元素a[0:n-1],現要在這n個元素中找出一特定的元素x。   我們首先想到的最簡單的是用順序搜尋方法,逐個比較a[0:n-1]中元素,直至找出元

演算法設計分析遞迴分治策略

 分治法:     將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。 (1)可行性:如果原問題可分割成k個子問題(1<k<=n),且這些子問題都可解,並可利用這些子問題的解求出原問題的解,那麼分治法就是可行的。 (2)分治法與

演算法設計分析入門篇(1.1演算法概述)——什麼是演算法

 我學習的視訊是網易雲平臺上的由王巨集志老師講的“演算法設計與分析”,這裡記錄學習筆記! 1.計算的定義   2.演算法的定義   3.問題的定義       問題是一種關係,下面這個例子中我們定義出一個我們常見的排序問題,之所以要弄出這種嚴格的定義是因為讓問題更嚴謹

演算法設計分析選擇排序

基本思想 選擇排序開始的時候,掃描整個序列,找到整個序列的最小記錄和序列中的第一個記錄交換,從而將最小記錄放到它在有序區的最終位置上,然後再從第二個記錄開始掃描序列,找到n-1個序列中的最小記錄,再和第二個記錄交換記錄。 一般地,第ii趟排序從第ii個記錄開

『嗨威說』演算法設計分析 - 動態規劃思想小結(HDU 4283 You Are the One)

本文索引目錄: 一、動態規劃的基本思想 二、數字三角形、最大子段和(PTA)遞迴方程 三、一道區間動態規劃題點撥昇華動態規劃思想 四、結對程式設計情況     一、動態規劃的基本思想:   1.1  基本概念:   動態規劃演算法簡單說,利用拆解問題思想,定義問題

演算法設計分析筆記(2):遞迴分治策略

宣告 1)本文僅供學術交流,非商用。具體引用的資料請看參考文獻。如果某部分不小心侵犯了大家的利益,請聯絡博主刪除。 2)本人才疏學淺,整理總結的時候難免出錯,還望各位前輩不吝指正,謝謝。 聯

演算法設計分析(一)——遞迴分治

目錄  D、走迷宮 提示: 提示:  NOJ 2018.9.21 A、二分查詢 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 給定一個單調遞增的整數序列,問某個整數是否在序列中。 輸入

演算法設計分析:第三章 分治 3.3二進位制大整數的乘法

/* 二進位制大整數的乘法: 請設計一個有效的演算法,可以進行兩個n 位二進位制大整數的乘法運算 設x = 3141, A = 31 B=41 y = 5327, C = 53,D=27 x*y = AC*2^n + (AD + BC)*2^(n/2) + BD

演算法設計分析(三)貪心演算法

前面兩篇:貪心演算法的特點設計要素:貪心法適用於組合優化問題。求解過程是多不判斷過

演算法設計分析:第四章 動態規劃 4.2TSP貨郎擔問題

/* 如果對於任意數目的n個城市,分別用1~n編 號,則這個問題歸結為在有向帶權圖中,尋找一 條路徑最短的哈密爾頓迴路問題。 這裡,V表示城市頂點,(i,j) ∈E 表示城市之 間的距離,用鄰接矩陣C表示城市之間的距離。 思想: 1設d(i,V-{i})表示從頂點i出發

計算機演算法設計分析——遞迴分治策略(一)

遞迴: 直接或者間接地呼叫自身的演算法稱為遞迴。用函式自身給出定義的函式成為遞迴函式。 使用遞迴技術往往使函式的定義和演算法的描述簡潔且易於理解。有些資料結構,如二叉樹等,由於其本身固有的遞迴特性,特別適合用遞迴的形式來描述。另外,還有一些問題,雖然其本身沒

演算法設計分析(二)動態規劃

第一篇:動態規劃(Dynamic Programming)求解過程是多階段決策過程

演算法設計分析——動態規劃(一)矩陣連乘

動態規劃——Dynamic programming,可以說是本人一直沒有啃下的骨頭,這次我就得好好來學學Dynamic programming. OK,出發! 動態規劃通常是分治演算法的一種特殊情況,它一般用於最優化問題,如果這些問題能夠: 1.能夠分解為規模更小的子問題 2.遞迴的

演算法設計分析——分治法

前言 本文重點回顧了卜老師課堂上關於分治演算法的一些常見的問題。加油吧!ヾ(◍°∇°◍)ノ゙ 分治法(Divide and Conquer) 當面對一個問題的時候,我們可能一下子找不到解決問題的方法。此時,我們可以考慮將問題規模最小化,先看看當問題規模變小以後,我們如何去解決

演算法設計分析04-排序問題

①氣泡排序:量量比較待排序資料元素的大小,發現兩個資料元素的次序相反時進行交換,直到沒有反序的資料元素為止。時間複雜度是O(n*2)。穩定的。下面給出兩種排序演算法,我比較喜歡第二種,因為第二種才能真正解釋冒泡的原理 public class bubble1 {    &n

演算法設計分析03-十進位制轉二進位制問題

10進位制數轉2 進位制數 題目:2 進位制除了 0,1,還可以用 2 表示。例如: 1-> 1 2-> 10 or 02 3->11 4 ->100 or 020 or 012 問題:這樣一個十進位制數轉為二進位制數,就不是唯一的了。現求十進位制數 N 轉換為這種二進位制數

演算法設計分析02-走臺階問題

走臺階問題,一次可以走1,2,3級,都 N級臺階的方法數 。 初始:f(0) = 0; f(1) =1; f(2) = 1 + 1 = 2; 遞推公式:f(n) = f(n - 1) + f(n-2) + f(n - 3) 解題思路: 因為一次可以走1,2,3級,所以在第

演算法設計分析01-連結串列的逆置

一.最常用的方法: LNode*  ReverseList(LNode* head) {     if (head == NULL)         return NULL;  &nbs

演算法設計分析05-最近點對演算法

1.題目描述: 設S是平面上n個點的集合,在這一節中,我們考慮在S中找到一個點對p和q的問題,使其相互距離最短。換句話說,希望在S中找到具有這樣性質的兩點p1 = (x1,y1)和p2 = (x2,y2),使它們間的距離在所有S中點對間為最小 2.解題思路 一共分為三種情況 情況1: