分治策略(入门)

  小编今天学习了一下 分治策略(参考 算法导论),并用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个值的时间对比情况:

猜你喜欢

转载自www.cnblogs.com/a-runner/p/12218021.html
今日推荐