//分治:劃分、解子問題、組合
//每個遞迴演算法均可以轉換為迭代演算法
#include #include //尋找最大最小元素,最大比較次數 3*n/2 - 2
minmax(low,high)
if(high - low = 1)
if(arr[low] < arr[high])
return (arr[low],arr[high])
else
return (arr[high],arr[low])
end if
else
mid = (low+high)/2
(x1,y1) = minmax(low,mid)
(x2,y2) = minmax(mid+1,high)
x = min(x1,x2)
y = max(y1,y2)
return (x,y)
end if
//尋找第k小元素或中項 o(nlogn)
//每個遞迴呼叫劃分步驟中,丟棄元素的固定部分,問題規模不斷減小
select (a,low,high,k)
p = high - low + 1
if(p < 44)
sort(a)
return a[k]
else
q = p/5;
把a分成q組,每組5個元素;若不整除,排除剩餘的元素
q中的每一組單獨排序,找出中項,放入集合m
mm = select(a,1,q,q/2) //找出中項集合的中項
把a分成三組:a1=
case
|a1| >= k : return select(a1,1,|a1|,k)
|a1| + |a2| >= k: return mm
|a1| + |a2| < k: return select(a3,1,|a3|,k-|a1|-|a2|)
end case
end if
//大整數乘法
//把n位大整數x 分為n/2位的兩部分 x1,x2,則x = x1*2^(n/2) + x2 冪運算可以做移位
//x*y = x1*y1*2^n + ((x1+x2)(y1+y2))-x1*y1 - x2*y2)*2^(n/2)+x2*y2 只需要3次n/2規模的乘法和6次加減運算
//t(n) = 3t(n/2)+bn o(n^1.59)
//矩陣乘法
//傳統的o(n^3):乘法:n^3 加法:n^3-n^2
//優化 o(n^2.81):乘法7次、加法18次: t(n) = 7*t(n/2) + 18*(n/2)^2a
/*增加減法以減少乘法:設定7個d,根據a,b的子矩陣計算,利用d組成c
*/ //最近點對問題 o(n*log n)
輸入:平面上n個點的集合s
輸出:s中兩點的最小距離
以x座標遞增排序s
y = 以y座標遞增排序s
z = cp(1,n)
cp(low,high)
if(high - low +1 <=3)
直接計算距離
else
mid = (high + low)/2
x0 = x(s[mid]) //找出x的中線
zl = cp(low,mid)
zr = cp(mid+1,high)
z = min(zl,zr)
k = 0
//從y中抽取t,找出那些在中線附近z區域的點
for(i = 1~n)
if(|x(y[i] - x0| <= z)
k = k+1
t[k] = y[i]
end if
end for
z0 = 2z
for(i = 1~k-1)
//對這些點上部的7個點比較距離
for(j = i+1 ~ min)
if(d[t[i],t[j]) < z0
z0 = d(t[i],t[j])
end for
end for
z = min(z,z0)
end if
return z
演算法設計與分析基礎 分治法
1.將乙個問題劃分為同一型別的若干子問題,子問題最好規模相同 2.對子問題求解 一般使用遞迴方法 3.有必要的話,合併子問題的解,得到原始問題的答案 下圖描述的是將乙個問題劃分為兩個較小子問題的例子,也是最常見的情況 1.主要思想 對於乙個需要排序的陣列a 0 n 1 將其一分為二 a 0 n 2 ...
演算法設計與分析 分治法(js實現)
特徵能否利用分治法完全取決於問題是否具有這條特徵,如果具備了前兩條特徵,而不具備第三條特徵,則可以考慮貪心演算法或動態規劃。偽 divide and conquer p if p n0 adhoc p 解決小規模的問題 divide p into smaller subinstances pl,p....
演算法分析與設計 分治演算法
在電腦科學中,分治法是一種很重要的演算法。字面上的解釋是 分而治之 就是把乙個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題 直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。這個技巧是很多高效演算法的基礎,如排序演算法 快速排序,歸併排序 傅利葉變換 快速傅...