分治策略
一.在分治策略中,递归地求解一个问题,在每层递归中应用如下三个步骤:
二.分治法分析归并排序
(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]
七.完全二叉树的网格布局
规定时间,得到递归式