[算法]倒置个数(python)

倒置个数

题目地址

又名:逆序对的个数

题目描述

Description

有一个由N个实数构成的数组,如果一对元素A[i]和A[j]是倒序的,即i<j但是A[i]>A[j]则称它们是一个倒置,设计一个计算该数组中所有倒置数量的算法。要求算法复杂度为O(nlogn)

Input

输入有多行,第一行整数T表示为测试用例个数,后面是T个测试用例,每一个用例包括两行,第一行的一个整数是元素个数,第二行为用空格隔开的数组值。

Output

输出每一个用例的倒置个数,一行表示一个用例。

Sample Input 1

1
8
8 3 2 9 7 1 5 4

Sample Output 1

17
题目解析

就是在并归排序的基础上统计一下逆序数的个数.

即:分别求出左半边的逆序数和右半边的逆序数,并求和统计

如何求逆序数?
  1. 左数组和右数组都是相对有序的,如果右数组的数小于左数组的数(此时构成逆序),则跟左数组中所有大于该数的数(排列在该数的右面)都构成逆序
例子

[8 3] num+=1 --> [3 8]

[2 9] num+=0 --> [2 9]

此时左数组为[3 8] 右数组为 [2 9]

此时 2 < 3 构成一个逆序,则 2与左数组中所有大于3的数都构成逆序, 因此num += 2

代码实现
def merge(l_arr, r_arr, num):
    res_arr = []
    i, j = 0, 0
    while i < len(l_arr) and j < len(r_arr):
        if l_arr[i] <= r_arr[j]: # 这里面是小于等于,经过排查已经纠错
            res_arr.append(l_arr[i])
            i += 1
        else:
            res_arr.append(r_arr[j])
            num += len(l_arr) - i  # 多了一行代码,用来统计个数
            j += 1
    if i < len(l_arr):
        res_arr = res_arr + l_arr[i:]
    if j < len(r_arr):
        res_arr = res_arr + r_arr[j:]
    return res_arr, num


def merge_sort(arr):
    if len(arr) <= 1:
        return arr, 0  # 多返回一个指,用来统计倒置个数
    m = len(arr) >> 1
    l_arr, l_num = merge_sort(arr[:m])
    r_arr, r_num = merge_sort(arr[m:])
    return merge(l_arr, r_arr, (l_num + r_num)) # 倒置个数求和


if __name__ == '__main__':
    case_num = int(input().strip())
    for i in range(case_num):
        _ = input()
        arr = [int(x) for x in input().strip().split(" ")]
        _, num = merge_sort(arr)
        print(num)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值