归并排序 + 统计数组逆数对个数 + 取余[Python]

剑指offer有一道题求数组中逆序数对的个数,用Python写了如下代码:

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        p = 0
        num = 1000000007
        while data:
            d_min = min(data)
            d_ind = data.index(d_min)
            p += d_ind
            data.pop(d_ind)
        ans = p%num
        return ans


ans = Solution()
data = [1,2,3,4,5,6,7,0]
res = ans.InversePairs(data)

然而复杂度过高,一直通不过~后来看了大家的讲解,看到用归并排序解决这个问题(但是Python依旧通不过),不过之前也没写过归并排序的代码,所以记录如下:

归并排序:

归并排序使用了二分法。

这里显示了归并排序的第一步,将数组按照middle进行递归拆分,最后分到最细之后再将其使用对两个有序数组进行排序的方法对其进行排序。

两个有序数组排序的方法则非常简单,同时对两个数组的第一个位置进行比大小,将小的放入一个空数组,然后被放入空数组的那个位置的指针往后 移一个,然后继续和另外一个数组的上一个位置进行比较,以此类推。到最后任何一个数组先出栈完,就将另外i一个数组里的所有元素追加到新数组后面。

(a) 把长度为4的数组分解成两个长度为2的子数组;

(b) 把长度为2的数组分解成两个成都为1的子数组;

(c) 把长度为1的子数组 合并、排序并统计逆序对

(d) 把长度为2的子数组合并、排序,并统计逆序对;

牛客网讲解链接:https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5

代码:

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.count = 0

    def InversePairs(self, lis):
        # write code here
        self.merge_sort(lis)
        return self.count % 1000000007

    def merge_sort(self, lis):
        if len(lis) <= 1:
            return lis
        mid = len(lis)//2
        left = lis[:mid]
        right = lis[mid:]
        left_merge = self.merge_sort(left)
        right_merge = self.merge_sort(right)
        return self.merge(left_merge, right_merge)

    def merge(self, left, right):
        merge = []
        while left and right:
            if left[0] > right[0]:
                self.count += len(left)
                merge.append(right.pop(0))
            else:
                merge.append(left.pop(0))
        if left:
            merge.extend(left)
        else:
            merge.extend(right)
        return merge

ans = Solution()
#a = [1, 7, 8, 5, 6, 4, 2, 3]
a = [1, 2, 3, 4, 5,6, 7, 0]
res = ans.InversePairs(a)
b = 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值