《剑指offer》刷题系列——(七十一)数组中的逆序对

题目

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5

思路

暴力法是两个for循环遍历数组,比较数组中的每一对数字,但是会超时。
如何减少比较次数?
利用归并排序的思想。
原数组: [7,5,6,4]
一分为二:left = [7,5],right = [6,4]
对每个子数组排序:left = [5,7],right = [4,6]
归并的过程中寻找逆序对:
left中的第一个元素5大于right中的第一个元素4,可以构成一个逆序对。由于两个子数组都是排好序的,所以5后面的元素都大于4,可以不再进行比较就能确定,都可以和4构成逆序对。

在归并排序的基础上添加统计逆序对个数即可。

代码

class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        self.count = 0

        def Merge(left, right, s):
            i, j, k = 0, 0, 0
            while i < len(left) and j < len(right):
                if left[i] <= right[j]:
                    s[k] = left[i]
                    i += 1
                    k += 1
                else:
                    self.count += len(left)-i
                    s[k] = right[j]
                    j += 1
                    k += 1

            while i < len(left):
                s[k] = left[i]
                i += 1
                k += 1
            while j < len(right):
                s[k] = right[j]
                j += 1
                k += 1

        def MergeSort(nums):
            if len(nums) < 2:
                return nums
            mid = len(nums)//2
            left = nums[:mid]
            right = nums[mid:]
            MergeSort(left)
            MergeSort(right)
            Merge(left, right, nums)

        MergeSort(nums)
        return self.count

复杂度

时间复杂度: O(nlog⁡n)
空间复杂度: O(n)

猜你喜欢

转载自blog.csdn.net/weixin_44776894/article/details/107692144