分治法一般步骤:
- 分(divide):将大问题分解为一些小问题
- 治(conguer):分别处理(解决)这些小问题
- 合(combine):组合各个小问题处理之后的结果
常见的分治法有:
归并排序(mergeSort)
T(n)=2T(n/2)+Θ(n)
由主方法可知,时间复杂度为 Θ(nlog2n)二分搜索(binary search)
T(n)=T(n/2)+Θ(1)
时间复杂度为 Θ(log2n)乘方运算
xn
由于以前没有写过乘方运算的递归代码,就在这里贴上python代码def power(x,n): if n == 1: return x if n % 2 == 0: v = power(x, n / 2) return v * v v = power(x, n / 2) return v * v * x
T(n)=T(n/2)+Θ(1)
时间复杂度为 Θ(log2n)费波纳茨数列
F(n)=⎧⎩⎨01F(n−1)+F(n−2)n=0n=1n>1
递归函数求解费波纳茨数列
def fib(n): if n == 0 or n == 1: return n return fib(n - 1) + fib(n - 2)
T(n)=T(n−1)+T(n−2)
时间复杂度为 Ω(ϕn)[ϕ=1+5√2]
可见时间复杂度为指数级迭代法求解费波纳茨数列(自下而上递归)
def fib(n): if n == 0 or n == 1: return n a = 0 b = 1 i = 1 while i < n: tmp = b b = a + b a = tmp i += 1 return b
时间复杂度为 Θ(n)
数学方法
fib(n)=⌈ϕnn⌉
时间复杂度为 Θ(log2n)
这是一种理想情况,因为在现代计算机中,用浮点数表示实数会产生误差。- 矩阵法
[fib(n+1)fib(n)fib(n)fib(n−1)]=[1110]n
时间复杂度 Θ(log2n)
下面证明该矩阵公式:
-
n=1
,显然成立
[fib(2)fib(1)fib(1)fib(0)]=[1110] - 假设
n=n−1
公式成立,那么
[fib(n)fib(n−1)fib(n−1)fib(n−2)]=[1110]n−1 -
n=n
[fib(n+1)fib(n)fib(n)fib(n−1)]=[fib(n)fib(n−1)fib(n−1)fib(n−2)]×[1110]=[1110]n
-
n=1
,显然成立
矩阵法求解费波纳茨数列,python代码
def mul_matrix(ma,mb):
ma_rows = len(ma)
ma_clos = len(ma[0])
mb_cols = len(mb[0])
res = [[] for row in range(ma_rows)]
for row in range(ma_rows):
for col in range(mb_cols):
value = 0
for k in range(ma_clos):
value += ma[row][k] * mb[k][col]
res[row].append(value)
return res
def power(L,n):
if n == 1:
return L
if n % 2 == 0:
v = power(L,n/2)
return mul_matrix(v,v)
v = power(L,n/2)
return mul_matrix(mul_matrix(v,v),L)
def fib(n):
if n == 0:
return 0
m = [[1,1],
[1,0]]
res = power(m,n)
return res[0][1]
if __name__ == '__main__':
for i in range(20):
print '%5d' % fib(i)
输出结果:
>>>
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181