493. 翻转对

求数组A的翻转对:

reversePairs(A) = reversePairs(B) + reversePairs(C) + cross_middle(B, C)

A = B + C

cross_middle(B, C)表示跨越B,C的答案(B相较于C的翻转对)


class Solution:
    def cross_middle(self, nums, l, r):
        res, mid = 0, (l+r) >> 1
        j = mid + 1
        for i in range(l, mid+1):
            while j <= r and nums[i] > 2 * nums[j]:
                res += mid - i + 1
                j += 1
        return res 
    def merge_sort(self, nums, nums_sorted, l, r):
        if l >= r:
            return 0
        mid = (l + r) >> 1
        res = self.merge_sort(nums, nums_sorted, l, mid) + self.merge_sort(nums, nums_sorted, mid+1, r) + self.cross_middle(nums, l, r)
        # 归并排序,方便cross_middle函数的计算
        i, j, k = l, mid+1, l
        while i <= mid and j <= r:
            if nums[i] <= nums[j]:
                nums_sorted[k] = nums[i]
                i += 1
            else:
                nums_sorted[k] = nums[j]
                j += 1
            k += 1
        while i <= mid:
            nums_sorted[k] = nums[i]
            i += 1
            k += 1
        while j <= r:
            nums_sorted[k] = nums[j]
            j += 1
            k += 1

        # 使 nums[l, r+1] 有序
        for k in range(l, r+1):
            nums[k] = nums_sorted[k]
        return res

    def reversePairs(self, nums: List[int]) -> int:
        if not nums:
            return 0
        nums_sorted = [0] * len(nums)
        return self.merge_sort(nums, nums_sorted, 0, len(nums) - 1)