51. 数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

方法1:暴力求解
使用简单的循环判断,我们的思路是顺序扫描整个数组,每扫到一个数字,逐个比较该数自和它后面的数字大小
这种方法时间复杂度为O(n**2),空间复杂度O(1)
这种方法跑不通oj,时间复杂度很高

class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        length = len(nums)
        if length == 0 or length==1:
            return 0
        res = 0
        for i in range(length-1):
            count = 0
            for j in range(i,length):
                if nums[i]>nums[j]:
                    count+=1
            res += count
        return res

方法2:基于归并排序的统计

 下面我们这样来思考:[7,5,6,4]

1.先把数组分成两个部分[7,5],[6,4],在继续分割成[[7],[5]],[[6],[4]]两个组;
2.接着进行合并,先合并[[7],[5]],由于7>5,在这个组内存在一个逆序排列,根据由小到大排序得到[5,7];同理对[[6],[4]]进行同样的操作,得到[4,6],同样也存在一个逆序对;
3.下面进行组间的合并s1=[5,7],s2=[4,6],此时我们需要需要一个辅助数组s来存储排序好的数组,我们设置两个指针分别指向s1和s2的尾部,当前指向的数字为7和6,由于这两个数组都是排好序的,所以7会大于s2中的所有数字,即与7能组成逆序对的个数为s2数组的长度,然后将7放入s的末尾,再比较5和6,5<6,不存在逆序对,将6放入s中,此时s=[6,7],再次比较5和4,5>4,存在逆序对,逆序对的数目等于1,将5放入s,将4放入s;
4.如此下去,可以发现上面的过程就是归并排序的过程,只需简单的加入统计逆序对变量即可;

class Solution(object):
    def reversePairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        result = [0]
        def Merge_sort(s):
            n = len(s)
            if n < 2:
                return
            mid = n // 2
            s1 = s[0:mid]
            s2 = s[mid:n]
            Merge_sort(s1)
            Merge_sort(s2)
            Merge(s1,s2,s)

        def Merge(s1,s2,s):
            len_s1 = len(s1) - 1
            len_s2 = len(s2) - 1
            temp = len(s) - 1
            
            while len_s1 >=0 and len_s2 >= 0:
                if s1[len_s1] > s2[len_s2]:
                    s[temp] = s1[len_s1]
                    result[0] += len_s2 + 1
                    len_s1 -= 1
                    temp -= 1
                else:
                    s[temp] = s2[len_s2]
                    len_s2 -= 1
                    temp -= 1
                    
            while len_s1 >= 0:
                s[temp] = s1[len_s1]
                len_s1 -= 1
                temp -= 1
            while len_s2 >= 0:
                s[temp] = s2[len_s2]
                temp -= 1
                len_s2 -= 1

        Merge_sort(nums)
        return result[0]

 方法3:二分查找与插入

class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        cnt, tmp = 0, []
        for num in nums[::-1]:
            cnt += bisect_left(tmp, num)#二分插入,计算已有列表(后面的先插入)比num小的数字
            insort(tmp, num)
        return cnt
posted @ 2020-03-31 11:07  USTC丶ZCC  阅读(157)  评论(0编辑  收藏  举报