Michael Tsai 2011/2/25
Algorithm Design Strategy
不是教你”某種演算法”
而是怎麼用”某些策略”來”設計演算法”
第一課: 各個擊破=Divide & Conquer
什麼是Divide‐and‐Conquer
當碰到一個問題的時候:
1. 把問題分解(Divide)成一些比較小的同樣問題
2. if 問題小到可以直接解決(Conquer),
then 直接解決
else 遞迴地呼叫自己的分身解決較小的這些問題
3. 把已解決的小問題解答結合(Combine)起來變成 原來的問題的解答
Base case
Recursive case
Divide and Conquer的好處
容易能解決困難的問題
思考模式: 解決最簡單的case + 整合小問題的答案變成大問 題的答案
通常也容易因此想出更有效率的演算法
執行時間的複雜度比較低
適合平行運算 (Multi‐core systems!)
更有效的記憶體存取
小的subprogram與它的subprogram們的資料都可以放在在 CPU的cache裡面, 而不需要存取速度比較慢的主記憶體
例子1: 河內塔
規則:
1. 每次可以移動每根棍子上最上面的盤子, 到其他 棍子已有的盤子上.
2. 大盤子不能放在小盤子上面
3. 一次只能移動一個盤子
例子1: 河內塔
目標: n個盤子, 柱子1移到柱子3
1 2 3
n個盤子
例子1: 河內塔
1 2 3
n=1時, 直接可以把盤子移過去 Base Case:
例子1: 河內塔
1 2 3
1. n‐1個盤子, 從柱子1移到柱子2 3. n‐1個盤子, 從柱子2移到柱子3
2. 把最大的盤子從柱子1移到柱子3 n>1時:
Recursive Case:
例子1: 河內塔
Divide在哪裡?
原本: n個盤子從柱子1移到柱子3
分成:
1. n‐1個盤子從柱子1移到柱子2
2. 1個盤子從柱子1移到柱子3
3. n‐1個盤子從柱子2移到柱子3
Combine在哪裡?
這個例子不需要額外combine
比較小的同樣問題
例子2: Merge Sort
Input: n個數字
Output: 照順序由大排到小
n個數字
n個排好順序的數字
例子2: Merge Sort
1個數字
1個排好順序的數字 n=1時, 沒有排序的問題, 直接輸出
Base Case:
啥都不用做
例子2: Merge Sort
n個數字
n個排好順序的數字 n>1時
Recursive Case:
n/2個數字 n/2個數字
Divide: 分成兩等分,分別排序
Combine: 兩個排序好的數列合併成一個
分別排序:
比較小的同 樣問題
例子2: Merge Sort
Divide在哪裡?
原本: 把n個數字排序
分成:
2個 (n/2個數字排序)
Combine在哪裡?
把兩個排好的數列合併成一個數列
在這裡鍵入方程式。計算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
Recurrences
例1. Merge Sort, n個數字排序:
如果n=1時: 直接輸出.
如果n>1時:
分成2個 (n/2個數字排序)
把兩個排好的數列合併成一個數列
2 /2 Θ Θ 1
Θ 1 2 2 Θ
,if 1 ,if 1
細節
例: 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時)
股市大亨
菜瓜布股份有限公司股票股價
未卜先知, 已知未來的股價走勢(內線?)
問: 如何找出可以使獲利最大的買進賣出時機?
0 20 40 60 80 100 120
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
股價
股價
股市大亨:嘗試一
嘗試一: 有沒有什麼絕招? (Θ 1 的方法)
找最低點當買入點, 往後找之後的最高點當賣出 點
找最高點當賣出點, 往前找之前的對低點當買入 點
以上找出的是否為正確解?
答:否.
股市大亨:嘗試二
嘗試二: 暴力法
不用大腦的方法
每種可能性都試試看 (窮舉法)
如此的話要花多少時間?
有幾種可能性: 2 Θ
就算每種可能性都只花 1 也是要Ω
能不能更好?
股市大亨:嘗試三
嘗試三: 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
大刀一砍再來想
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
股市大亨:嘗試三
Maximum subarray可能出現的情形:
n/2個數字 n/2個數字
1. 只包含左半部數字(low to mid) 2. 只包含右半部數字(mid+1 to high) 3. 兩邊的數字都包含.因為必須是連續
的, 所以必須跨過中間點
最後三種比較, 找出總和最大的一個即可.
1. 和 2. 可從n/2個數字的結果得到.
3. 必須另外計算.
Recursive Case:
股市大亨:嘗試三
3. 如何找出包含中間點的maximum subarray呢?
n/2個數字 n/2個數字
中間點
(1) 尋找以中點開始, 左邊的 maximum subarray
(2) 尋找以中點開始, 右邊的 maximum subarray
(3) 合併(1)和(2)即為包含中間點的maximum subarray 所花時間? Θ
low ……….. mid mid+1 ……….. …. high
股市大亨:嘗試三
n=1的時候
maximum subarray?
就是它自己.
Base Case:
股市大亨 之 酥多扣的(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)
股市大亨 之 酥多扣的(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,high) (cross-low,cross-high,cross-sum)=find-max-crossing-
subarray(A,low,mid,high)
if left-sum>=right-sum and left-sum>=cross-sum return (left-low,left-high,left-sum)
else 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
執行時間分析
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
下次…
其他Divide‐and‐Conquer的例子
矩陣相乘
找中位數
如何解遞迴式