遞迴原則
1.總是要有一種基準情形(基準情形比結束條件的叫法更確切)
2.總是要朝著基準情形的方向推進
3.假設所有的遞迴呼叫都能正常執行
4.在求解乙個問題的同乙個例項時,不要在不同的遞迴呼叫中做重複的工作
舉例:def
fib(n):
if n<=1:
return
1else:
return fib(n-1) + fib(n-2)
這個遞迴fib(n-1)這個方法本身會呼叫fib(n-2),這樣會使執行時間以指數的速度增長
乙個解決辦法是將已經算出的值儲存起來備用
最大子串行和方法一:窮舉法
def max_sub_sequence_sum(ori_list):
length = len(ori_list)
max_sum = 0
for i in range(length):
for j in range(i, length):
this_sum = 0
for k in range(i, j):
this_sum += ori_list[k]
if this_sum > max_sum:
max_sum = this_sum
return max_sum
這種方法複雜度是 o(n**3)
方法二:窮舉法
def max_sub_sequence_sum(ori_list):
length = len(ori_list)
max_sum = 0
for i in range(length):
this_sum = 0
for j in range(i, length):
this_sum += ori_list[j]
if this_sum > max_sum:
max_sum = this_sum
第一種方法中k經歷的元素j同樣會經歷,所以這一層迴圈是不必要的,此時複雜度是o(n**2)
方法三:遞迴
這個方法使用了「分治」的策略,「分」是把問題分成大致相等的兩個子問題,然後對子問題再分,遞迴的求解。「治」是把子問題的結果合併。
這個問題中,最大子串行和可能在三個地方出現:左部分,右部分,中間部分(更確切的描述為:至少包含左部分最後乙個元素和右部分第乙個元素的部分,這部分的最大和通過計算左部分的最大和與右部分的最大和相加得到,注意:此處說的左部分和右部分指的是從分割點開始向兩側延伸時取得的最大值)
def max_sub_sum(ori_list, left, right):
if left == right: # left是固定傳了0,當==時,就證明list裡只有乙個元素了,所以這裡可以這麼寫
if ori_list[left] > 0
return ori_list[left]
else:
return
0# 對這裡存有疑問,個人認為,當left == right時,直接return ori_list[left]就可以了,因為對於它的上一層遞迴來講,0和負數都不會成為比較中的大值
center = (left + right) / 2
max_left_sum = max_sub_sum(ori_list, left, center)
max_right_sum = max_sub_sum(ori_list, center + 1, right)
max_left_border_sum, left_border_sum = 0, 0
for i in range(center, left - 1, -1):
left_border_sum += ori_list[i]
if left_border_sum > max_left_border_sum:
max_left_border_sum = left_border_sum
max_right_border_sum, right_border_sum = 0, 0
for i in range(center + 1, right + 1, 1):
right_border_sum += ori_list[i]
if right_border_sum > max_right_border_sum:
max_right_border_sum = right_border_sum
return
max(max_left_sum, max_right_sum, max_left_border_sum + max_right_border_sum)
max_sub_sum(ori_list, 0, len(ori_list) - 1)
方法四:
def max_sub_sequence_sum(ori_list);
length = len(ori_list)
this_sum = max_sum = 0
for i in range(length):
this_sum += ori_list[i]
if this_sum > max_sum:
max_sum = this_sum
elif this_sum < 0:
this_sum = 0
# 當加出來的數是負數的時候,它一定會使後面和它相加的數變小
return max_sum
先從左開始算,如果沒有出現負數,會一直取到從左開始的最大值,如果出現負數的話,證明不能繼續向右累加了(此時max_sum還是保留著的)
對分查詢
給定乙個整數x和乙個排序好的list,求x在list中的位置,如果不存在,返回-1
def
binary_search
(ori_list, x):
left, right = 0, len(ori_list) -1
while left <= right:
mid = (left + right) / 2
if ori_list[mid] < x:
left = mid + 1
elif ori_list[mid] > x:
right = mid - 1
else:
return mid
return -1
冪運算–x的n次冪def
pow(x, n):
if n == 0:
return
1elif n == 1:
return x # 基準條件
elif n % 2: # 奇數
return pow(x, n/2) * x
else:
return pow(x, n/2)
使用遞迴,讓n次乘法運算變為2logn次
快速排序–這是「分治」策略的另乙個例子–友情贈送def
fast_sort
(ori_list):
if ori_list:
if len(ori_list) != 1:
fast_value = ori_list[0]
else:
return ori_list
else:
return ori_list
left, right = ,
for i in ori_list[1:]:
if i < fast_value:
else:
return fast_sort(left) + [fast_value] + fast_sort(right)
資料結構與演算法分析第二章12題
問題描述 1 求最小子序列和 2 求最小正子串行和 3 求最大子串行乘積 分析 1 求最小子序列和其實和求最大子串行和是一樣一樣的。最高效的o n 的時間複雜度演算法思想是 假設有n個元素的陣列,最大子串行和為從i到j。那麼想想 i,j 是否可以繼續向左右擴充套件呢?如果不能,制約條件是什麼?對於最...
資料結構與演算法分析
資料結構與演算法分析可以稱得上是程式設計師必須修煉的內功心法。資料的儲存結構 資料元素在計算機中的儲存方式 資料的操作集合 對一種資料型別的資料所有操作,例如對資料的增刪改查等等!演算法分析主要分析 下面是一些常用資料結構 一 線性表 1.陣列實現 2.鍊錶 二 棧與佇列 三 樹與二叉樹 1.樹2....
資料結構與演算法分析
資料結構 大量資料的組織方法 演算法分析 演算法執行時間的估算。涉及到計算效率。設想,如果能把時間限制從16年減至不到1秒,不很神奇嗎?在很多問題中,乙個重要的觀念是 寫出乙個可以工作的程式並不夠。如果這個程式在巨大的資料集上執行,執行時間就成了重要的 問題。演算法,是為求解乙個問題需要遵循的 被清...