[LeetCode](面试题51)数组中的逆序对

题目

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

示例 1:

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

限制:

0 <= 数组长度 <= 50000

解题思路

利用归并排序算法,在合并两个子序列的时候统计逆序对个数。
复杂度分析:
时间复杂度:O(NlogN),这里 N 是数组的长度。复杂度是归并排序的时间复杂度,直接看递归树的结点个数或者使用主定理分析,归并的回收每一步计算逆序对的个数是 O(1) 的;
空间复杂度:O(N)。

代码

class Solution:
    # 在数组 nums 的区间 [left, right] 统计逆序对
    def count_reverse_pairs(self, nums, left, right, tmp):
        if left == right:
            return 0
        mid = left + (right-left)//2
        left_cnt = self.count_reverse_pairs(nums, left, mid, tmp)
        right_cnt = self.count_reverse_pairs(nums, mid+1, right, tmp)
        if nums[mid]<=nums[mid+1]:
            # 即整个数组已经有序,则无需合并,所以不用计算横跨两个区间的逆序对,直接返回
            return left_cnt + right_cnt
        merge_cnt = self.merge_and_count(nums, left, mid, right, tmp)
        return left_cnt + merge_cnt + right_cnt
    
    def merge_and_count(self, nums, left, mid, right, tmp):
        # [left, mid] 有序,[mid + 1, right] 有序
        for i in range(left, right+1):
            tmp[i] = nums[i]
        i = left
        j = mid+1
        count = 0
        for k in range(left, right + 1):
            if i > mid:
                nums[k] = tmp[j]
                j += 1
            elif j > right:
                nums[k] = tmp[i]
                i += 1
            elif tmp[i] <= tmp[j]:
                # 此时前数组元素出列,不统计逆序对
                nums[k] = tmp[i]
                i += 1
            else:
                # 此时后数组元素出列,统计逆序对
                nums[k] = tmp[j]
                j += 1
                count += (mid - i + 1)
        return count

    def reversePairs(self, nums: List[int]) -> int:
        n = len(nums)
        if n<2:
            return 0
        # 用于归并的辅助数组
        tmp = [0]*n
        return self.count_reverse_pairs(nums, 0, n-1, tmp)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值