Conquer I Divide and

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移到柱子2 3. 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的話, 直接移動過去.

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

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

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

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

𝑇(𝑛 − 1)

𝑇(𝑛 − 1) 𝑇(1)

𝑇 1 = Θ(1) 𝑇 𝑛

𝑇 𝑛 = Θ(1)

2𝑇 𝑛 − 1 + 𝑇(1)

,if 𝑛 = 1 ,if 𝑛 > 1

(15)

Recurrences

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

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

 如果n>1時:

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

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

𝑇(𝑛)

2 𝑇(𝑛/2) Θ(𝑛) Θ(1)

𝑇 𝑛 = Θ(1) 2𝑇 𝑛

2 + Θ(𝑛)

,if 𝑛 = 1 ,if 𝑛 > 1

(16)

細節

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

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

 甚至

𝑇 𝑛 = Θ(1) 𝑇 𝑛

2 + 𝑇( 𝑛

2 ) + Θ(𝑛)

,if 𝑛 = 1 ,if 𝑛 > 1

𝑇 𝑛 = Θ(1) 2𝑇 𝑛

2 + Θ(𝑛)

,if 𝑛 = 1 ,if 𝑛 > 1

𝑇 𝑛 = 2𝑇 𝑛

2 + Θ(𝑛)

假設: (大部分時候都成立) 1. Ceiling & floor functions

不影響recurrence的解 2. Boundary case -

n很小的時候通常

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

(17)

股市大亨

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

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

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

0 20 40 60 80 100 120

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

股價

股價

(18)

股市大亨:嘗試一

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

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

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

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

 答:否.

(19)

股市大亨:嘗試二

 嘗試二: 暴力法

 不用大腦的方法

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

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

 有幾種可能性: 𝑛

2 = 𝑛 𝑛−12 = Θ 𝑛2

 就算每種可能性都只花𝑂 1 也是要Ω(𝑛2)

 能不能更好?

(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 Price 100 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= (𝑙𝑜𝑤 + ℎ𝑖𝑔ℎ)/2

(left_low,left_high,left_sum)=Find_Maximum_Subarray(A,low,mid) (right_low,right_high,right_sum)=Find_Maximum_Subarray(A,mid+1,h igh)

(cross_low,cross_high,cross_sum)=Find_Max_Crossing_Subarray(A,lo w,mid,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 Case

Recursive Case Divide

Combine

Conquer

(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)

𝑇 𝑛 = Θ(1) 2𝑇 𝑛

2 + Θ(𝑛)

,if 𝑛 = 1 ,if 𝑛 > 1

解: T n = Θ(𝑛 log 𝑛)

(28)

Today’s Reading Assignment

 Cormen ch 4 – 4.1

(29)

下次…

 其他Divide-and-Conquer的例子

矩陣相乘

找中位數

 如何解遞迴式

數據

Updating...

參考文獻

相關主題 :