小编今天学习了一下 分治策略(参考 算法导论),并用python代码实现了一下 实例中的 方法。大家一起相互学习啦。
首先是 插入排序的方法:
时间复杂度为 (n^2)。
代码实现如下:
# 插入排序法 a = [2,1,6,5,4,8,9] for i in range(int(len(a))): for j in range(int(len(a))-1): if a[j] > a[j+1]: b = a[j] a[j] = a[j+1] a[j+1] = b print("增序列表" + str(a))
然后就是:
归并排序法,时间复杂度为 nlog(n):
# 归并排序法 a = [2,1,6,5,4,8,9] def merge(a, p, q, r): n1 = q - p + 1 n2 = r - q l1 = [] l2 = [] for i in range(n1): l1.insert(i, a[p+i]) for j in range(n2): l2.insert(j, a[j+q+1]) l1.append(1000) l2.append(1000) i = 0 j = 0 for k in range(p, r+1): if l1[i] <= l2[j]: a[k] = l1[i] i += 1 else: a[k] = l2[j] j += 1 def merge_sort(a, p, r): if p < r: q = int((p + r)/2) # print(q) merge_sort(a, p, q) merge_sort(a, q+1, r) merge(a, p, q, r) merge_sort(a, 0, 6) print(a)
归并排序就是用了 分治策略。
相关的问题 有——最大子数组问题。
诸如下述的列表:
代表着16天以来的股票增长情况,要求选出一天买入,一天卖出,最后获得盈利最大。
a = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
有两种情况,一种是暴力求解的方法,一种是利用分治策略。
首先,实现 暴力求解,就是列举出所有的情况,选取利益最大的情况。
依次遍历。
a = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7] max_sum = 0 for i in range(16): sum = 0 for j in range(i+1, 16): sum = sum + a[j] if sum>max_sum: max_sum = sum left = i+1 right = j print(left, right, max_sum)
另一种方法就是利用分治策略,任何连续数组必然是下列三中情况下的一种:
1 完全位于数组的low---mid 之中
2 完全位于数组的mid--high之中
3 数组跨越了 mid
def find_max_crossing(a, low, mid, high): left_sum = -1000 sum = 0 for i in range(mid, low-1, -1): sum = sum + a[i] if(sum>left_sum): left_sum = sum max_left = i right_sum = -1000 sum = 0 for j in range(mid+1, high+1): sum = sum + a[j] if(sum>right_sum): right_sum = sum max_right = j return (max_left, max_right, right_sum+left_sum) def find_max_subarray(a, low, high): if(low==high): return (low, high, a[low]) else: mid = int((low+high)/2) (left_low, left_high, left_sum) = find_max_subarray(a, low, mid) (right_low, right_high, right_sum) = find_max_subarray(a, mid+1, high) (cross_low, cross_high, cross_sum) = find_max_crossing(a, low, mid, high) if((left_sum>=right_sum) and (left_sum>=cross_sum)): return (left_low, left_high, left_sum) elif((right_sum>=left_sum)and(right_sum>=cross_sum)): return (right_low, right_high, right_sum) else: return (cross_low, cross_high, cross_sum) (a,b,c) = find_max_subarray(a, 0, 15) print(str(a) + '\n' + str(b) + '\n' + str(c))
下面 附上 两种方法在 数组有16个值的时间对比情况: