[每日一水] 求数组中的逆序对

还是一道经典的力扣题目:

https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/

俺是非科班出生的菜鸡,一大把年纪了,第一次写这个😭😭😭😭

熟悉归并排序的话,可以看下后边的分析直接写,如果写不出来,再copy代码

先上代码:

from typing import List
def merge(array, s1, e1, s2, e2):
    array_new = array.copy()
    # 规定从小到大
    
    CI = 0 # 初始化逆序数
    steps = (e1-s1+1) + (e2-s2+1)
    start = s1
    for i in range(steps):
        
        if s1 > e1:
            # 意思是左边的没了, (左边的本来应该小, 先没), 不存在逆序
            array_new[start+i] = array[s2]
            s2 += 1
            continue
            
        if s2 > e2:
            # 意思是右边的没了, (右边的本来应该大, 但是没了), 存在逆序
            array_new[start+i] = array[s1]
            s1 += 1
            continue
        
        if   array[s1] > array[s2]:
            array_new[start+i] = array[s2]
            s2 += 1
            CI += e1-s1+1 # 如果左边比右边大, 存在逆序
            
        elif array[s1]  <= array[s2]:
            array_new[start+i] = array[s1]
            s1 += 1
    
    # 不要以为 (无需改变原数组, 故而注释)
    array[start:e2+1] = array_new[start:e2+1]
    
    return CI
        


def mergeSort(array, start, end):
    # 规定从小到大排序
    
    CI = 0 # 数组中的逆序数, (实际上不用初始化)

    if len(array) == 0:
        return 0

    if end-start == 1:
        # 处理长度为 2 的情况
        if array[start] > array[end]:
            # 不能改变原数组结构了, 故而注释掉
            array[start] += array[end]
            array[end] = array[start] - array[end]
            array[start] = array[start] - array[end]
            return 1
        return 0
    
    if end == start:
        # 处理长度为 1 的情况
        return 0
    
    mid   = int((start + end) / 2)
    
    L_CT = mergeSort(array, start, mid) # 左半部分逆序数
    R_CT = mergeSort(array, mid+1, end) # 右半部分逆序数
    
    LR_CT = merge(array, start, mid, mid+1, end) # 左右两部分逆序数对比
    
    return CI + L_CT + R_CT + LR_CT



class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        length = len(nums)

        import numpy as np
        nums = np.array(nums)
        
        return mergeSort(nums, 0, length-1)
    
IC = Solution.reversePairs(None, [7,5,6,4])
print("逆序数:", IC)

建议先看上一篇博客:
[每日一水] 归并排序 Python实现

在数组求逆序对中,即使用了 Divide and Conquer ,算法复杂度依然是 O ( n 2 ) O(n^2) O(n2),为啥呢,因为在后期合并这一步的时候,依然是两层for循环,所以比较慢

所以依旧存在 比较大小的冗余,所以为了去除冗余,则 要千方百计引入结构,好喜欢卜老师的字啊:

在这里插入图片描述

也就是在归并排序两部分 merge 的时候,如果右半部分的某些元素要先于左半部分的某些元素插入时,则左半部分比该元素大的个数就是逆序数(废话),而如果左右两部分都存在从小到大的结构时,上述的那个个数就是:

左半部分序列长度 减去 左半部分的id [注意是否有加一减一的动作(id从0开始则不需要加减1)]


(该Slider截图参考自卜东波老师的课件)

如果你想不通为啥在递归调用 mergeSort 的时候,仔细看看上边儿那个图

B站也有卜老师的课
https://www.bilibili.com/video/BV1MK4y1W7Gm

感谢 卜老师

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值