特徵
能否利用分治法完全取決於問題是否具有這條特徵,如果具備了前兩條特徵,而不具備第三條特徵,則可以考慮貪心演算法或動態規劃。偽**
divide-and-
conquer
(p)if
(|p|
<= n0)
adhoc
(p);
//解決小規模的問題
divide p into smaller subinstances pl,p...
.pk;
//分解問題
for(i=
1,i<=k,i++
) yi=divide-and-
conquer
(pi)
;//遞迴的解各子問題
returnmrrge...
.yk)
;//將各子問題的解合併為原問題的解
人們從大量實踐中發現,在用分治法設計演算法時,最好使子問題的規模大致相同。即將乙個問題分成大小相等的k個子問題的處理方法是行之有效的。這種使子問題規模大致相等的做法是出自一種平衡(balancing)子問題的思想,它幾乎總是比子問題規模不等的做法要好。例子
求指定整型陣列的最大值和最小值。
傳統做法就是遍歷一遍下來求出最大值和最小值,時間複雜度是o(n)。
function
divide_conquer
(arr,
from
,to)
}else
if(to -
from==0
)}else;if
(result1[
"max"
]> result2[
"max"])
else
if(result1[
"min"
]> result2[
"min"])
else
return result;}}
var arr =[34
,5,6
,7111,7
,8,889,9
];console.
log(
divide_conquer
(arr,
0,arr.length-1)
);
二分搜尋給你一-個裝有16個硬幣的袋子。16個硬幣中有一 個是偽造的,並且那個偽造的硬幣比真的硬幣要輕一些。你的任務是找出這個偽造的硬幣。為了幫助你演算法描述完成這一任務,將提供臺可用來比較兩組硬幣重量的儀器,利用這台儀器,可以知道兩組硬幣的重量是否相同。
將16個硬幣分成a、b兩半;
將a放儀器的一邊, b放另-邊,如果a袋輕,則表明偽幣在a ,解子問題a即可,否則,解 子問題b。 例項
給定已按公升序排好序的n個元素a|0:n-1|,現要在這n個元素中找出特定元素x。
function
binarysearch
(arr, target));
// console.log(arr.sort((a, b) => ))
let left =0;
let right = arr.length -1;
while
(left <= right)
else
if(arr[mid]
< target)
else
}return
"該數不存在"
}binarysearch([
3,2,
1,3,
4,6,
7],1
);console.
log(
binarysearch([
3,2,
1,3,
4,6,
7],1
))
快速排序
思路偽**
template<
class
type
>
void
quicksort
(type a]
, int p, int r)
例項// 快速排序
/* 思想:二分的操作,遞迴的思想,分成左右兩個陣列,比當前小的放左邊,大的放右邊,重複以上操作,當遞迴到剩下的長度為<=1
時間複雜度 o(nlog n)
*/function
quick
(arr)
// 找到陣列的中間向,在原有的陣列中把他移除
let mid = math.
floor
(arr.length/2)
;let midvalue = arr.
splice
(mid,1)
[0];
// 準備左右兩個陣列,迴圈剩下陣列中的每一項,比當前小的放左邊,大的放右邊
let arrright =
, arrleft =
;for
(let i =
0;i)// 遞迴方式讓左右兩邊都排好序
return
quick
(arrleft)
.concat
(midvalue,
quick
(arrright));
}quick([
23,54,
67,57,
87,798,56,
1,2,
4])
快排的進一步思考
偽**
template<
class
type
>
int randomizedpartition
(type a[
], int p, int r)
歸併排序
演算法描述
若n為1 ,演算法終止;否則,將這一元素集合分割成兩個或更多個子集合,對每- -個子集合分別排序然後將排好序的子集合歸併為乙個集合。例項
function
mergesort
(arr)
const mid = math.
floor
(length /2)
;//分成左右兩個部分
const left = arr.
slice(0
, mid)
;const right = arr.
slice
(mid, length)
;return
merge
(mergesort
(left)
,mergesort
(right));
//要將原始陣列分割直至只有乙個元素時,才開始歸併
}function
merge
(left, right)
else
}//不可能同時存在left和right都有剩餘項的情況, 要麼left要麼right有剩餘項, 把剩餘項加進來即可
while
(il < left.length)
while
(ir < right.length)
return result;
}console.
log(
mergesort([
2,9,
1,8,
3,])
)
覆蓋殘缺棋盤
偽**
void
chessboard
(int tr, int tc, int dr, int dc, int size)
if(size ==1)
return
;intt= tile++
,//l型骨牌號
s= size/2;
//分割棋盤
//覆蓋左上角子棋盤
if(dr//特殊方格在此棋盤中
chessboard
(tr, tc, dr, dc, s)
;else
//覆蓋右上角子棋盤
if(dr=tc+ s)
/1特殊方格在此棋盤中
chessboard
(tr, tc+s, dr, dc, s)
;else
//覆蓋左下角子棋盤
if(dr>=tr+ s&&dc//特殊方格在此棋盤中
chessboard
(tr+s, tc, dr, dc, s)
;else
//覆蓋右下角子棋盤
if(dr>=tr+ s&& dc>=tc+ s)
//特殊方格在此棋盤中
chessboard
(tr+s, tc+s, dr, dc, s)
;else
}
複雜度分析
複雜度分析
0(1)k=0
t(k)= 4t(k-l)+o(1) k>0
t(n)=o(4k) 漸進意義下的最優演算法
演算法設計與分析基礎 分治法
1.將乙個問題劃分為同一型別的若干子問題,子問題最好規模相同 2.對子問題求解 一般使用遞迴方法 3.有必要的話,合併子問題的解,得到原始問題的答案 下圖描述的是將乙個問題劃分為兩個較小子問題的例子,也是最常見的情況 1.主要思想 對於乙個需要排序的陣列a 0 n 1 將其一分為二 a 0 n 2 ...
演算法設計與分析複習 分治法演算法描述
分治 劃分 解子問題 組合 每個遞迴演算法均可以轉換為迭代演算法 include include 尋找最大最小元素,最大比較次數 3 n 2 2 minmax low,high if high low 1 if arr low arr high return arr low arr high els...
演算法設計與分析之分治法 棋盤覆蓋
棋盤覆蓋問題要求在2 k 2 k 個方格組成的棋盤中,你給定任意乙個特殊點,用一種方案實現對除該特殊點的棋盤實現全覆蓋。建立模型如圖 解決方案就是利用分治法,將方形棋盤分成4部分,如果該特殊點在某一部分,我們就去遞迴他,如果不在某一部分,我們假設乙個點為特殊點,同樣遞迴下去,知道全覆蓋。左上角的子棋...