分治思维与归并排序

刷到归并,就此开坑,归并似乎用的是分治的思维

👉图解归并算法

👉参考详解 :其中诠释出,通过分治的方法,降低对比交换的次数,来降低时间复杂度

分治!就是把大问题肢解成同类小问题解决(递归)


二分法查询(用于有序数列)

通过设立center,把长数列中查询或计数的工作分到每一个部分当中去完成,最后合并(求和)

代码略


归并排序

def mergeSort(temp_list, number_list, left, right):
    if left == right:
        return
    elif left < right:
        center = (left + right)//2
        mergeSort(temp_list, number_list, left, center)
        mergeSort(temp_list, number_list, center+1, right)
        merge(temp_list, number_list, left, center, right)

    return number_list
    pass

def merge(temp_list, number_list, left, center, right):
    idx_l = left
    idx_r = center + 1
    idx_ct = 0
    while idx_r <= right:
        if number_list[idx_r] >= number_list[idx_l]:
            temp_list[idx_ct] = number_list[idx_l]
            idx_l += 1
            idx_ct += 1
            pass
        else:
            temp_list[idx_ct] = number_list[idx_r]
            idx_r += 1
            idx_ct += 1
        if idx_l > center:
            while idx_r <= right:
                temp_list[idx_ct] = number_list[idx_r]
                idx_r += 1
                idx_ct += 1

    while idx_l <= center:
        temp_list[idx_ct] = number_list[idx_l]
        idx_l += 1
        idx_ct += 1

    for i in range(idx_ct):
        number_list[left+i] = temp_list[i]

    for i in range(len(temp_list)):
        temp_list[i] = 0

    pass

def testMergesort():
    number_list = [364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]
    temp_list = [0 for i in range(len(number_list))]

    print(mergeSort(temp_list, number_list, 0, len(number_list)-1))

testMergesort()

 输出为:[3, 38, 45, 64, 67, 80, 82, 115, 142, 144, 147, 149, 162, 174, 181, 187, 219, 221, 233, 234, 235, 256, 259, 266, 267, 268, 275, 284, 288, 301, 315, 341, 355, 360, 364, 366, 380, 401, 406, 407, 416, 418, 425, 433, 446, 455, 460, 463, 465, 474, 478, 486, 497, 505, 516, 523, 550, 557, 569, 571, 575, 576, 583, 588, 601, 604, 630, 637, 648, 650, 655, 665, 667, 671, 697, 727, 735, 739, 746, 747, 773, 784, 795, 811, 848, 849, 863, 870, 874, 882, 930, 935, 936, 958, 965, 971, 973, 983, 993, 995]

* merge函数还可以做重构 


逆序对应用

逆序对指的是在一串数字中前大后小的数字对。归并的交换不重复,交换次数就可以用来统计逆序对的数量。

与排序的差别在于多了计数

 写的时候一定要注意count的计数的位置,以及left和right的限制

def InversePairs(data):
    # write code here
    temp = [0 for i in range(len(data))]
    count = mergeCount(data, temp, 0, len(data) - 1)
    print(temp)
    return count

def mergeCount(data, temp, left, right):
    count = 0
    if left == right:
        return 0
    center = (left + right) // 2
    count += mergeCount(data, temp, left, center)
    count += mergeCount(data, temp, center + 1, right)

    idx_l = left
    idx_r = center + 1
    idx_ct = 0
    while idx_r <= right and idx_l <= center:
        if data[idx_r] >= data[idx_l]:
            temp[idx_ct] = data[idx_l]
            idx_ct += 1
            idx_l += 1
            pass
        else:
            count += center + 1 - idx_l
            temp[idx_ct] = data[idx_r]
            idx_ct += 1
            idx_r += 1
            pass
        pass
    while idx_r <= right:
        temp[idx_ct] = data[idx_r]
        idx_ct += 1
        idx_r += 1
        pass
    while idx_l <= center:
        temp[idx_ct] = data[idx_l]
        idx_ct += 1
        # count += center + 1 - idx_l
        idx_l += 1
        pass

    for i in range(idx_ct):
        data[left + i] = temp[i]
        pass

    return count

def testInversePairs():
    data = [364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]
    print(InversePairs(data))

输出为:正常排序如上

逆序数为:2519

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值