【LeetCode】面试题51 逆序对

问题描述

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

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

限制: 0 <= 数组长度 <= 50000

问题分解

先用伪代码再现问题中的逻辑

if arr[i] > arr[j] and i < j , 则生成一个逆序对 n[i][j]

可推 : 拿出数组中的一个元素,对比之后的元素,只要大于之后的值,那么总数+1 ,这样得出来的就是暴力法

但是,显然暴力法是不可取的,因为会造成算法的超时

问题解决

归并排序

当归并排序执行合并数组的时候,可以比较两个数组指针对应的值,得出对应数组分别满足题目的数量,这样做相比暴力破解法可以大幅度降低执行时间。

具体解法参考下面代码,已经加了注释。

class Solution:
    def mergeSort(self, nums, tmp, l, r):
        if l >= r:
            return 0 #拆分到头
        mid = (l + r) // 2 # 找到中心段
        inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r) #并操作
        i, j, pos = l, mid + 1, l
        while i <= mid and j <= r: 
            if nums[i] <= nums[j]:  # 进行数据比对,满足条件就增加计数
                tmp[pos] = nums[i]
                i += 1
                inv_count += (j - (mid + 1))
            else:
                tmp[pos] = nums[j]
                j += 1
            pos += 1
        for k in range(i, mid + 1):
            tmp[pos] = nums[k]
            inv_count += (j - (mid + 1))
            pos += 1
        for k in range(j, r + 1):
            tmp[pos] = nums[k]
            pos += 1
        nums[l:r+1] = tmp[l:r+1] 
        return inv_count

    def reversePairs(self, nums: List[int]) -> int: # 开始
        n = len(nums) # 得到数组长度
        tmp = [0] * n # 定义0填充的数组作为临时空间
        return self.mergeSort(nums, tmp, 0, n - 1) # 执行递归方法

参考资料

  • https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
  • https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/shu-zu-zhong-de-ni-xu-dui-by-leetcode-solution/
发布了361 篇原创文章 · 获赞 464 · 访问量 174万+

猜你喜欢

转载自blog.csdn.net/diandianxiyu/article/details/105727337