mapreduce(分治演算法的應用) 是 google 大資料處理的三駕馬車之一,另外兩個是 gfs 和 bigtable。它在倒排索引、pagerank 計算、網頁分析等搜尋引擎相關的技術中都有大量的應用。
儘管開發乙個 mapreduce 看起來很高深,感覺遙不可及。實際上,萬變不離其宗,它的本質就是分治演算法思想,分治演算法。如何理解分治演算法?為什麼說 mapredue 的本質就是分治演算法呢?
分治演算法的主要思想是將原問題遞迴地分成若干個子問題,直到子問題滿足邊界條件,停止遞迴。將子問題逐個擊破(一般是同種方法),將已經解決的子問題合併,最後,演算法會層層合併得到原問題的答案。
.):# 不斷切分的終止條件
if problem is
none
: print_result
return
# 準備資料
data=prepare_data(problem)
# 將大問題拆分為小問題
subproblems=split_problem(problem, data)
# 處理小問題,得到子結果
subresult1=self.divide_conquer(subproblems[0]
,p1,
..…)
subresult2=self.divide_conquer(subproblems[1]
,p1,..
.)subresult3=self.divide_conquer(subproblems[2]
,p1,
.…)# 對子結果進行合併 得到最終結果
result=process_result(subresult1, subresult2, subresult3,..
.) 通過應用舉例分析理解分治演算法的原理其實並不難,但是要想靈活應用並在程式設計中體現這種思想中卻並不容易。所以,這裡這裡用分治演算法應用在排序的時候的乙個例子,加深對分治演算法的理解。
一般通過計算有序對或者逆序對的個數,來表示資料的有序度或逆序度。
假設我們有n
個資料,我們期望資料從小到大排列,那完全有序的資料的有序度就是 n(n
−1)/
2n(n-1)/2
n(n−1)
/2,逆序度等於 0;相反,倒序排列的資料的有序度就是 0,逆序度是 n(n
−1)/
2n(n-1)/2
n(n−1)
/2。q:如何程式設計求出一組資料的有序對個數或者逆序對個數呢?
因為有序對個數和逆序對個數的求解方式是類似的,所以這裡可以只思考逆序對(常接觸的)個數的求解方法。
方法2
leetcode169題
以分治實現
class
solution
(object):
defmajorityelement
(self, nums)
:# 【不斷切分的終止條件】
ifnot nums:
return
none
iflen
(nums)==1
:return nums[0]
# 【準備資料,並將大問題拆分為小問題】
left = self.majorityelement(nums[
:len
(nums)//2
])right = self.majorityelement(nums[
len(nums)//2
:])# 【處理子問題,得到子結果】
# 【對子結果進行合併 得到最終結果】
if left == right:
return left
if nums.count(left)
> nums.count(right)
:return left
else
:return right
leetcode53題由於左右區間計算累加和的方向不一致,因此,左右區間直接合併相加之後就是整個區間的和
最終返回左區間的元素、右區間的元素、以及整個區間(相對子問題)和的最大值
以分治實現
class
solution
:def
maxsubarray
(self, nums: list[
int])-
>
int:
# 【不斷切分的終止條件】
n =len(nums)
if n ==1:
return nums[0]
# 【準備資料,並將大問題拆分為小問題】
# 獲得左右最大子序和
left = self.maxsubarray(nums[
:n//2]
) right = self.maxsubarray(nums[n//2:
])# 【處理子問題,得到子結果】
# 獲得穿過中間的最大值
# 從右到左計算左側的最大子序和
max_l = nums[n//2-
1]# 左側最大子序和,初始為最右邊元素
tmp =
0# tmp用來記錄連續子陣列的和
for i in
range
( n//2-
1,-1
,-1)
:# 從右到左遍歷
tmp += nums[i]
max_l =
max(tmp ,max_l)
# 從左到右計算右側的最大子序和
max_r = nums[n//2]
# 右側最大子序和,初始為最左邊元素
tmp =
0for i in
range
(n//
2,n)
:# 從左到右遍歷
tmp += nums[i]
max_r =
max(tmp,max_r)
# 【對子結果進行合併 得到最終結果】
# 返回三個中的最大值
return
max(left,right,max_l+ max_r)
leetcode50題最終返回p
以分治實現
class
solution
:def
mypow
(self, x:
float
, n:
int)
->
float
:# 處理n為負的情況
if n <0:
x =1/x
n =-n # 【確定不斷切分的終止條件】
if n ==0:
return
1# 【準備資料,並將大問題拆分為小的問題】
if n%2==
1:# 【處理小問題,得到子結果】
return x * self.mypow(x,n-1)
# 【對子結果進行合併 得到最終結果】
return self.mypow(x*x,n/
2)
演算法 學習筆記
1.輸入輸出演算法至少有乙個或多個輸出 2.有窮性 3.確定性 4.可行性 1.正確性a.演算法程式沒有語法錯誤 b.演算法程式對於合法的輸入資料能夠產生滿足要求的輸出結果 c.演算法程式對於非法的輸入資料能夠得出滿足規格說明的結果 d.演算法對於精心選擇的,甚至刁難的測試資料都有滿足要求的輸出結果...
演算法學習筆記
複雜度分析 1.只關注迴圈次數最多的一行 2.總複雜度等於量級最大 的複雜度 3.巢狀 的複雜度等於巢狀 內外複雜度的乘積 單鏈表結構和順序儲存結構的優缺點 儲存分配方式 時間效能 空間效能 單鏈表結構 用一組任意的儲存單元存放線性表元素 查詢 o n 插入和刪除 找到某位置的指標後,插入和刪除的時...
演算法學習筆記
影象分割是機器視覺後續處理的基礎,通過分割提取影象中的目標區域,方便後續進一步分析處理。分水嶺分割演算法 傳統的分水嶺演算法,是基於數學形態學的分割方法。其基本思想是,將2d影象視為3d地形 其中,畫素的座標 地形的位置,畫素的灰度 地形的高度 每乙個區域性極小值及其周圍區域稱為集水盆地,而集水盆地...