Divide and Co nquer I

29  Download (0)

全文

(1)

Michael Tsai 2013/9/12

(2)

Algorithm Design Strategy

 不是教你”某種演算法”

 而是怎麼用”某些策略”來”設計演算法”

 第一課 : 各個擊破 =Divide & Conquer

(3)

什麼是 Divide-and-Conquer

 當碰到一個問題的時候 :

1. 把問題分解 (Divide) 成一些比較小的同樣問題

2. if 問題小到可以直接解決 (Conquer),

then 直接解決

else 遞迴地呼叫自己的分身解決較小的這些問題

3. 把已解決的小問題解答結合 (Combine) 起來變 成原來的問題的解答

Base

case Recursive

case

(4)

Divide and Conquer 的好處

容易能解決困難的問題

思考模式 : 解決最簡單的 case + 整合小問題的答案變成 大問題的答案

通常也容易因此想出更有效率的演算法

執行時間的複雜度比較低

適合平行運算 (Multi-core systems!)

更有效的記憶體存取

小的 subprogram 與它的 subprogram 們的資料都可以放在在 CPU 的 cache 裡面 , 而不需要存取速度比較慢的主記憶體

(5)

例子 1: 河內塔

 規則 :

1. 每次可以移動每根棍子上最上面的盤子 , 到其 他棍子已有的盤子上 .

2. 大盤子不能放在小盤子上面

3. 一次只能移動一個盤子

(6)

例子 1: 河內塔

目標 : n 個盤子 , 柱子 1 移到 柱子 3

1 2 3

n 個盤子

(7)

例子 1: 河內塔

1 2 3

n=1 時 , 直接可以把盤子移過去 Base

Case:

(8)

例子 1: 河內塔

1 2 3

1. n-1 個盤子 , 從柱子 1 移到柱子 23. n-1 個盤子 , 從柱子 2 移到柱子 3

2. 把最大的盤子從柱子 1 移到柱子 3 n>1 時 :

Recursive Case:

(9)

例子 1: 河內塔

 Divide 在哪裡 ?

 原本 : n 個盤子從柱子 1 移到柱子 3

 分成 :

1. n-1 個盤子從柱子 1 移到柱子 2

2. 1 個盤子從柱子 1 移到柱子 3

3. n-1 個盤子從柱子 2 移到柱子 3

 Combine 在哪裡 ?

這個例子不需要額外 combine

比較小的同樣問題

(10)

例子 2: Merge Sort

 Input: n 個數字

 Output: 照順序由大排到小

n 個數字

n 個排好順序的數字

(11)

例子 2: Merge Sort

1 個數字

1 個排好順序的數字 n=1 時 , 沒有排序的問題 , 直接輸出 Base

Case:

啥都不用做

(12)

例子 2: Merge Sort

n 個數字

n 個排好順序的數字 n>1 時

Recursive Case:

n/2 個數字 n/2 個數字

Divide: 分成兩等分 , 分別排 序

Combine: 兩個排序好的數列合併成一個

分別排序 : 比較小的同 樣問題

(13)

例子 2: Merge Sort

 Divide 在哪裡 ?

 原本 : 把 n 個數字排序

 分成 :

2 個 (n/2 個數字排序 )

 Combine 在哪裡 ?

把兩個排好的數列合併成一個數列

(14)

 計算 divide-and-conquer 的演算法執行時間

用遞迴式最自然

 例 1. 河內塔 , 移動 n 個盤子 :

 如果的話 , 直接移動過去 .

 如果的話 , 分為以下步驟 :

1. n-1 個盤子從柱子 1 移到柱子 2

2. 1 個盤子從柱子 1 移到柱子 3

3. n-1 個盤子從柱子 2 移到柱子 3

 

� (�− 1)

 

� (�− 1)

 

� (1)

 

 

( 1 ) =Θ(1)

 

( )

� (� )=

{

2� (� −1)+� (1)Θ(1)

    ,if

,if  

(15)

Recurrences

 例 2. Merge Sort, n 個數字排序 :

 如果 n=1 時 : 直接輸出 .

 如果 n>1 時 :

分成 2 個 (n/2 個數字排序 )

把兩個排好的數列合併成一個數列

� (�)

 

2

 

� (�/2) Θ(�)

 

Θ(1)

 

  ()=

{

2

(

Θ (1)2

)

+Θ (�)    ,if ,if

(16)

細節

 例 : Merge Sort 的 n 不是偶數時 , 就會變成

 通常我們卻很豪爽的使用

 甚至

  ()=

{

(

⌈ �2

)

+� ( ⌊ �Θ(1)2 ⌋ )+Θ(�) ,if  ,if  

  ()=

{

2

(

Θ (1)2

)

+Θ (�) ,if  ,if  

  ()=2

(

2

)

+Θ (�)

假設 : ( 大部分時候都成 立 )

1. Ceiling & floor functions 不影響 recurrence 的解 2. Boundary case -

n 很小的時候通常 execution

time=constant ( 不 一定只是 n=1 時 )

(17)

股市大亨

菜瓜布股份有限公司股票股價

未卜先知 , 已知未來的股價走勢 ( 內線 ?)

問 : 如何找出可以使獲利最大的買進賣出時機 ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 0

20 40 60 80 100 120

股價

股價

(18)

股市大亨 : 嘗試一

 嘗試一 : 有沒有什麼絕招 ? ( 的方法 )

 找最低點當買入點 , 往後找之後的最高點當賣 出點

 找最高點當賣出點 , 往前找之前的對低點當買 入點

 以上找出的是否為正確解 ?

 答 : 否 .

 

(19)

股市大亨 : 嘗試二

 嘗試二 : 暴力法

 不用大腦的方法

 每種可能性都試試看 ( 窮舉法 )

 如此的話要花多少時間 ?

 有幾種可能性 :

 就算每種可能性都只花也是要

 能不能更好 ?

 

(20)

股市大亨 : 嘗試三

嘗試三 : Divide-and-Conquer 的方法

首先先把原本的問題稍微轉換

題目變成在一列中找出此一數列的一連續子數列 , 使其總合為最大 , 又稱 Maximum Subarray Problem

 

Day 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Pric

e 10

0 113 110 85 105 102 86 63 81 101 94 106 101 79 94 90 97 13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7 Day 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Pric

e 10

0 113 110 85 105 102 86 63 81 101 94 106 101 79 94 90 97 13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7

(21)

 大刀一砍再來想

n 個數字

n/2 個數字 n/2 個數字

n 個數字的 maximum subarray

n/2 個數字的 maximum subarray n/2 個數字的 maximum subarray

假設可以找到兩個 n/2 大 小的 maximum

subarray

如何找到 n 個數字的 maximum subarray?

Recursive Case:

low 中間點

………..

mid

mid+1 ………..

…. high

(22)

股市大亨 : 嘗試三

 Maximum subarray 可能出現的情形 :

n/2 個數字 n/2 個數字

1. 只包含左半部數字 (low to mid)

2. 只包含右半部數字 (mid+1 to high)

3. 兩邊的數字都包含 . 因為必須是 連續的 , 所以必須跨過中間點

最後三種比較 , 找出總和最大的一個即 可 .

1. 和 2. 可從 n/2 個數字的結果 得到 .

3. 必須另外計算 . Recursive

Case:

(23)

股市大亨 : 嘗試三

 3. 如何找出包含中間點的 maximum subarray 呢 ?

n/2 個數字 n/2 個數字

中間點

(1) 尋找以中點開始 , 左邊 的 maximum subarray

(2) 尋找以中點開始 , 右邊 的 maximum subarray

(3) 合併 (1) 和 (2) 即為包含中間點的 maximum subarray

所花時間 ?

Θ(�)

 

low

………..

mid

mid+1 ………..

…. high

(24)

股市大亨 : 嘗試三

 n=1 的時候

 maximum subarray?

 就是它自己 .

Base Case:

(25)

股市大亨 之 酥多扣的 (pseudo-code)

Find_Max_Crossing_Subarray(A, low, mid, high) left_sum=-

sum=0

for i=mid downto low sum=sum+A[i]

if sum>left_sum left_sum=sum max_left=i right_sum=-

sum=0

for j=mid+1 to high sum=sum+A[i]

if sum>right_sum right_sum=sum max_right=j

return (max_left, max_right, left_sum+right_sum)

 

A: array 本身

low: array 最小的 index

mid: 左半部 array 的最大 index high: array 最大的 index

(26)

股市大亨 之 酥多扣的 (pseudo-code)

Find_Maximum_Subarray(A,low,high) if high==low

return (low,high,A[low]) else

mid=

(left_low,left_high,left_sum)=Find_Maximum_Subarray(A,low,mid)

(right_low,right_high,right_sum)=Find_Maximum_Subarray(A,mid+1,high) (cross_low,cross_high,cross_sum)=Find_Max_Crossing_Subarray(A,low,mi d,high)

if left_sum>=right_sum and left_sum>=cross_sum return (left_low,left_high,left_sum)

else if right_sum>=left_sum and right_sum>=cross_sum return (right_low,right_high,right_sum)

else

return (cross_low,cross_high,cross_sum)

 

Base

CaseRecursive Case Divide

Combin e

Conque r

(27)

執行時間分析

 n 個數字找 max-subarray

 Base case: n=1 的時候直接 return.

 Recursive case:

Divide: 2 個 n/2 個數字找 max subarray

Combine:

1. 確認 n>1, 計算中間點位置等等

2. 尋找通過 mid 的 max subarray

3. 比較三個 max subarray 的大小決定最後結果

 

( 1 ) =Θ(1)

 

( )

2

 

( �/2 )

Θ(�)

 

Θ(1)

 

  ()(1)+2

(

2

)

+Θ()+Θ(1)=2

(

2

)

+Θ(�)

Θ(1)

 

  ()=

{

2

(

Θ (1)2

)

+Θ (�)    ,if ,if   解 :

(28)

Today’s Reading Assignment

 Cormen ch 4 – 4.1

(29)

下次…

 其他 Divide-and-Conquer 的例子

矩陣相乘

找中位數

 如何解遞迴式

數據

Updating...

參考文獻

相關主題 :