分治策略

一.在分治策略中,递归地求解一个问题,在每层递归中应用如下三个步骤:

 

二.分治法分析归并排序

(1)把原数组分成两部分进行处理

(2)递归求解这两部分

(3)把求解好的两部分合并起来

 

三.二分查找:在数组中查找x的位置

(1)分:把x和已排序好数组的中间值进行比较

(2)治:在子数组中递归

(3)合并:Nothing 

T(n)=T(n/2)+θ(1)

=θ(lgn)

 

四.乘方问题:给定x,和n,要求计算xn

(1)分:n/2(n偶数)或(n-1)/2(n奇数)

(2)治:xn/2或者x(n-1)/2

(3)合并:nothing或*x

T(n)=T(n/2)+θ(1)

=θ(lgn)

 

五.矩阵乘法

斐波那契数:F(n)=F(n-1)+F(n-2)其中(n>=2)

(1)一般矩阵乘法

 1 #矩阵乘法 O(n*3)
 2 def square_matrix_multiply(A,B):
 3     C = []
 4     n = len(A)#A的阶
 5     C = [[0 for col in range(n)] for row in range(n)]#生成n*n的全0矩阵
 6     for i in range(0,n):
 7         for j in range(0,n):
 8             for k in range(0,n):
 9                 C[i][j]=C[i][j]+A[i][k]*B[k][j]#矩阵乘法规则
10     return C
11 A=[[1,3],[7,5]]
12 B=[[6,8],[4,2]]
13 print(square_matrix_multiply(A, B))
14 --------------------------------------------
15 [[18, 14], [62, 66]]
矩阵乘法

 

(2)简单的递归分治

 1 #递归分治法-矩阵乘法
 2 def square_matrix_multiply_recursive(A, B):
 3     n = len(A)
 4     C = [[0 for col in range(n)] for row in range(n)]
 5     if n == 1:
 6         C[0][0] = A[0][0] * B[0][0]
 7     else:
 8         (A11, A12, A21, A22) = partition_matrix(A)
 9         (B11, B12, B21, B22) = partition_matrix(B)
10         (C11, C12, C21, C22) = partition_matrix(C)
11         C11 = add_matrix(square_matrix_multiply_recursive(A11, B11), square_matrix_multiply_recursive(A12, B21))
12         C12 = add_matrix(square_matrix_multiply_recursive(A11, B12), square_matrix_multiply_recursive(A12, B22))
13         C21 = add_matrix(square_matrix_multiply_recursive(A21, B11), square_matrix_multiply_recursive(A22, B21))
14         C22 = add_matrix(square_matrix_multiply_recursive(A21, B12), square_matrix_multiply_recursive(A22, B22))
15         C = merge_matrix(C11, C12, C21, C22)
16     return C
17 
18 #分解矩阵,把矩阵分成4分
19 def partition_matrix(A):
20     n = len(A)
21     n2 = int(n / 2)
22     #生成四个初始零矩阵
23     A11 = [[0 for col in range(n2)] for row in range(n2)]
24     A12 = [[0 for col in range(n2)] for row in range(n2)]
25     A21 = [[0 for col in range(n2)] for row in range(n2)]
26     A22 = [[0 for col in range(n2)] for row in range(n2)]
27     #给这四个矩阵赋值
28     for i in range(0, n2):
29         for j in range(0, n2):
30             A11[i][j] = A[i][j]
31             A12[i][j] = A[i][j + n2]
32             A21[i][j] = A[i + n2][j]
33             A22[i][j] = A[i + n2][j + n2]
34     return (A11, A12, A21, A22)
35 
36 #合并矩阵,把四个矩阵合并为一个
37 def merge_matrix(A11, A12, A21, A22):
38     n2 = len(A11)
39     n = 2 * n2
40     A = [[0 for col in range(n)] for row in range(n)]
41     for i in range(0, n):
42         for j in range(0, n):
43             if i <= (n2 - 1) and j <= (n2 - 1):
44                 A[i][j] = A11[i][j]
45             elif i <= (n2 - 1) and j > (n2 - 1):
46                 A[i][j] = A12[i][j - n2]
47             elif i > (n2 - 1) and j <= (n2 - 1):
48                 A[i][j] = A21[i - n2][j]
49             else:
50                 A[i][j] = A22[i - n2][j - n2]
51     return A
52 
53 #添加矩阵,把A 和 B对应添加进一个矩阵C
54 def add_matrix(A, B):
55     n = len(A)
56     C = [[0 for col in range(n)] for row in range(n)]
57     for i in range(0, n):
58         for j in range(0, n):
59             C[i][j] = A[i][j] + B[i][j]
60     return C
61 
62 A=[[1,3],[7,5]]
63 B=[[6,8],[4,2]]
64 C=square_matrix_multiply_recursive(A,B)
65 print(C)
66 ----------------------------------------------------------
67 [[18, 14], [62, 66]]
矩阵乘法-分治思想

 

(3)Strassen算法 

 

 

六.最大子数组:寻找A中最大的非空连续子数组

 1 #最大子数组
 2 
 3 #求跨越中点的最大子数组
 4 def find_max_crossing_subarray(A, low, mid, high):
 5     # 先求A[low,mid]的最大子数组,一定是【A[i],mid】
 6     left_sum = float("-inf")#目前为止找到的左边的最大和
 7     sum = 0#A【i..mid 】中所有值的和
 8     max_left = 0#左边的最大下标
 9     max_right = 0#右边的最大下标
10     for i in range(mid, low - 1, -1):
11         sum = sum + A[i]
12         if sum > left_sum:
13             left_sum = sum
14             max_left = i
15     #先求A[mid+1,high]的最大子数组,一定是【mid+1,A[j]】
16     right_sum = float("-inf")
17     sum = 0
18     for j in range(mid + 1, high + 1):
19         sum = sum + A[j]
20         if sum > right_sum:
21             right_sum = sum
22             max_right = j
23     #返回下标和值
24     return [max_left, max_right, left_sum + right_sum]
25 
26 import math
27 
28 #分治法求解最大子数组,返回子数组的左右下标和总值
29 def find_maximum_subarray(A, low, high):
30     if high == low:
31         return (low, high, A[low])
32     else:
33         mid = math.floor((low + high) / 2)
34         #递归求解在左边,在右边和跨中点的最大子数组
35         [left_low, left_high, left_sum] = find_maximum_subarray(A, low, mid)
36         [right_low, right_high, right_sum] = find_maximum_subarray(A, mid + 1, high)
37         [cross_low, cross_high, cross_sum] = find_max_crossing_subarray(A, low, mid, high)
38         if left_sum >= right_sum and left_sum >= cross_sum:
39             return [left_low, left_high, left_sum]
40         elif right_sum >= left_sum and right_sum >= cross_sum:
41             return [right_low, right_high, right_sum]
42         else:
43             return [cross_low, cross_high, cross_sum]
44 
45 A=[13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]
46 
47 print(find_maximum_subarray(A, 0, len(A) - 1))
48 -----------------------------------------------------------------------
49 [7, 10, 43]
最大子数组

 

 

七.完全二叉树的网格布局

规定时间,得到递归式

 

posted on 2018-07-25 20:33  温润有方  阅读(284)  评论(0编辑  收藏  举报