點擊藍色 「小鹿動畫學編程」 關注我哦!
git
加個 「星標」 ,天天一篇動畫餵飽你!web
![](http://static.javashuo.com/static/loading.gif)
做者 | 江子抑
算法
來源 | 編程拯救世界編程
主要思想
三步走
分解:分解原問題爲結構相同的子問題(即尋找子問題)數組
解決:當分解到容易求解的邊界後,進行遞歸求解微信
合併:將子問題的解合併成原問題的解數據結構
![分治算法三步走](http://static.javashuo.com/static/loading.gif)
歸併排序
思想
三步走
分解:將序列劃分爲兩部分app
解決:遞歸地分別對兩個子序列進行歸併排序ide
合併:合併排序後的兩個子序列svg
舉例
10, 4, 6, 3, 8, 2, 5, 7
![序列分解](http://static.javashuo.com/static/loading.gif)
10, 4 排序合併後:4, 10
6, 3 排序合併後:3, 6
8, 2 排序合併後:2, 8
5, 7 排序合併後:5, 7
……
![上部分爲「分解」,下部分爲「解決」與「合併」](http://static.javashuo.com/static/loading.gif)
實現
def merge_sort(lst):
# 從遞歸中返回長度爲1的序列
if len(lst) <=
1:
return lst
middle = len(lst) /
2
# 1.分解:經過不斷遞歸,將原始序列拆分紅 n 個小序列
left = merge_sort(lst[:middle])
right = merge_sort(lst[middle:])
# 進行排序與合併
return merge(left, right)
def merge(left, right):
i, j =
0,
0
result = []
# 2.解決:比較傳入的兩個子序列,對兩個子序列進行排序
while i < len(left)
and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i +=
1
else:
result.append(right[j])
j +=
1
# 3.合併:將排好序的子序列合併
result.extend(left[i:])
result.extend(right[j:])
return result
真題演練
爲運算表達式設計優先級
LeetCode 241. 爲運算表達式設計優先級: https://leetcode-cn.com/problems/different-ways-to-add-parentheses/
題目描述
+
,
-
以及
*
。
輸入: "2-1-1"
輸出: [0, 2]
解釋:
((2-1)-1) = 0
(2-(1-1)) = 2
輸入: "2*3-4*5"
輸出: [-34, -14, -10, -10, 10]
解釋:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
思路
x op y
(
op
爲運算符,
x
和
y
爲數) 的算式而言,
它的結果組合取決於 x
和 y
的結果組合數,而
x
和
y
又能夠寫成形如
x op y
的算式。
x op y
中的
x
和
y
:
以運算符分隔的左右兩側算式解。
分解:按運算符分紅左右兩部分,分別求解
解決:實現一個遞歸函數,輸入算式,返回算式解
合併:根據運算符合並左右兩部分的解,得出最終解
實現
class Solution:
def diffWaysToCompute(self, input: str) -> List[int]:
# 若是隻有數字,直接返回
if input.isdigit():
return [int(input)]
res = []
for i, char
in enumerate(input):
if char
in [
'+',
'-',
'*']:
# 1.分解:遇到運算符,計算左右兩側的結果集
# 2.解決:diffWaysToCompute 遞歸函數求出子問題的解
left = self.diffWaysToCompute(input[:i])
right = self.diffWaysToCompute(input[i+
1:])
# 3.合併:根據運算符合並子問題的解
for l
in left:
for r
in right:
if char ==
'+':
res.append(l + r)
elif char ==
'-':
res.append(l - r)
else:
res.append(l * r)
return res
總結
找到子問題並分解
解決子問題(遞歸)
合併子問題的解
LeetCode 932. 漂亮數組: https://leetcode-cn.com/problems/beautiful-array
LeetCode 105. 從前序與中序遍歷序列構造二叉樹: https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
參考資料
OI Wiki: 遞歸 - 分治:https://oi-wiki.org/basic/divide-and-conquer/
有熱門推薦👇
1.【認知】如何超過大部分人?
2.【GitHub】這門神課拯救了我薄弱的計算機基礎
3.【算法】動畫: 快速排序 | 如何求第 K 大元素?
4.【數據結構】動畫:二叉樹在實際中的應用(下)
「小鹿動畫學編程」用動畫的形式和你分享技術!
長按識別二維碼關注
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
在看和轉發
都會帶來更多好運
本文分享自微信公衆號 - 小鹿動畫學編程(IT_Animation)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。