35. 数组中的逆序对 ***这道题挺难的

题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007


思路
思路一:
暴力解,两个循环,时间复杂度,但是会超出运行时间,导致失败。
思路二:
分治的思想,将数组不断一分为二,直到数组中只有两个元素,统计逆序对个数。然后对相邻的两个子数组进行合并,由于已经统计了这两对子数组内部的逆序对,因此需要把这两对子数组进行排序,避免在之后的统计过程中重复统计。在合并的时候也要计算组间的逆序对个数。
逆序对的总数 = 左边数组中的逆序对的数量 + 右边数组中逆序对的数量 + 左右结合成新的顺序数组时中出现的逆序对的数量
整个过程是一个归并排序的算法。
归并排序的性能不受输入数据的影响,时间复杂度始终都是。代价是需要额外的内存空间。


代码实现

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        # 思路一:暴力解,两个循环
        # 运行超时,暴力解不行哦
        length = len(data)
        if(length == 0):
            return 0
        else:
            num = 0
            for i in range(length-1):
                point = data[i]
                for j in range(i,length):
                    if(data[i]>data[j]):
                        num += 1
            return num%1000000007

归并排序的题解:

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        num, new_list = self.mergeSort(data)
        return num%1000000007

    def mergeSort(self, data):
        # 逆序对个数
        InversePairsNum = 0
        # 归并过程
        def merge(left,right):
            # 合并时发现的逆序对个数
            InversePairsNum = 0
            result = [] # 保存归并后的结果
            i = j = 0
            while(i<len(left) and j<len(right)):
                if left[i] <= right[j]:
                    result.append(left[i])
                    i += 1
                else:
                    result.append(right[j])
                    j += 1
                    # 当右边的元素被插入时,证明这个元素比左边的剩下的所有元素都小
                    # 可以组成len(left)-i个逆序对
                    InversePairsNum = InversePairsNum + (len(left)-i)
            result = result + left[i:] + right[j:] # 剩余的元素直接添加到末尾,大概率是空的
            return InversePairsNum, result
        # 
        if len(data) <= 1:
            return 0, data
        else:
            mid = len(data)//2 # //是向下取整
            num_left, left = self.mergeSort(data[:mid])
            num_right, right = self.mergeSort(data[mid:])
            num_merge, new_list = merge(left, right)
            InversePairsNum = num_left + num_right + num_merge
            return InversePairsNum, new_list

可以参考归并排序
归并排序 Python 代码实现如下:

def mergeSort(nums):
    # 归并过程
    def merge(left, right):
        result = []  # 保存归并后的结果
        i = j = 0
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result = result + left[i:] + right[j:] # 剩余的元素直接添加到末尾
        return result
    # 递归过程
    if len(nums) <= 1:
        return nums
    mid = len(nums) // 2
    left = mergeSort(nums[:mid])
    right = mergeSort(nums[mid:])
    return merge(left, right)

参考文献:
Python实现十大经典排序算法