剑指Offer:数组中的逆序对Java/Python

1.题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。即输出P%1000000007

2.算法描述

本来没有时间限制的话,直接用交换类的排序,比如插入或者冒泡,交换多少次就有多少逆序对。但是这里有时间限制, 只 能 用 O ( n l o g n ) 的 算 法 \red{只能用O(nlogn)的算法} O(nlogn)
所以就用归并排序呗。
归 并 排 序 是 在 归 并 的 时 候 消 除 逆 序 对 的 , 所 以 我 们 在 归 并 的 时 候 , 要 找 出 每 归 并 一 个 元 素 , 我 们 消 除 了 多 少 个 逆 序 对 。 \red{归并排序是在归并的时候消除逆序对的,所以我们在归并的时候,要找出每归并一个元素,我们消除了多少个逆序对。}

举例如下:

比如我们现在要归并左子数组 [ 2 , , 6 , 10 , 11 , 15 ] [2,,6,10,11,15 ] [2,6101115]右子数组 [ 1 , 5 , 7 , 8 ] [1,5,7,8 ] [1578],我写的Java代码是从尾部开始归并Python代码是从头部开始归并。以从尾部归并为例。
我们用两个指针 i , j i,j ij 分别指向左右子数组的尾部,比较它们指向的数的大小,如果 i i i指向的数大于 j j j指向的数,那么 i 指 向 的 数 必 然 大 于 j 指 向 的 右 子 数 组 以 及 以 前 的 所 有 数 字 \red{i指向的数必然大于j指向的右子数组以及以前的所有数字} ij
在这里 15 > 8 15>8 15>8,那么 15 必 然 大 于 右 子 数 组 所 有 数 \red{15必然大于右子数组所有数} 15,那么 对 于 15 有 多 少 的 逆 序 对 \red{对于15有多少的逆序对} 15?显然就是 j 到 右 子 数 组 头 部 有 多 少 个 元 素 , 就 有 多 少 个 逆 序 对 \red{j到右子数组头部有多少个元素,就有多少个逆序对} j,这里是4。

3.代码描述

3.1.Java代码

#由于Python语言时间的限制 有时可能会通不过
# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        if not data:
            return 0
        copy = data[:]
        return self.mergeSort(data, copy, 0, len(data)-1) % 1000000007
    def mergeSort(self, data, copy, left, right):
        if left >= right:
            copy[left] = data[left]
            return 0
        mid = (left + right) / 2
        leftCount = self.mergeSort(data, copy, left, mid)
        rightCount = self.mergeSort(data, copy, mid+1, right)
        count = 0
        i = left
        j = mid+1
        index = left
        while i <= mid and j <= right:
            if data[i] <= data[j]:
                copy[index] = data[i]
                i += 1
            else:
                copy[index] = data[j]
                count += mid-i+1
                if count>=1000000007:
                    count %= 1000000007
                j += 1
            index += 1
        while i <= mid:
            copy[index] = data[i]
            i += 1
            index += 1
        while j <= right:
            copy[index] = data[j]
            j += 1
            index += 1
        data[left:right+1] = copy[left:right+1]
        return (count + leftCount + rightCount) % 1000000007
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值