JZ35 数组中的逆序对

这篇博客探讨了如何使用归并排序算法来计算数组中的逆序对数量,并针对Python实现进行了优化,使得在处理大规模数据时也能避免超时。文章详细介绍了归并排序的分治思想,并附带了一个实例代码,展示了如何通过合并过程来统计逆序对。

描述

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


对于50\%50%的数据,size\leq 10^4size≤104
对于100\%100%的数据,size\leq 10^5size≤105

讨论组说用Python大多超时,试了一下讨论组一个方法居然通过了。先看懂,回过头来看C++的。

看样子用的是归并排序

count = 0
class Solution:
    def InversePairs(self, data):
        global count
        def MergeSort(lists):
            global count
            if len(lists) <= 1:
                return lists
            num = int( len(lists)/2 )
            left = MergeSort(lists[:num])
            right = MergeSort(lists[num:])
            r, l=0, 0
            result=[]
            while l<len(left) and r<len(right):
                if left[l] < right[r]:
                    result.append(left[l])
                    l += 1
                else:
                    result.append(right[r])
                    r += 1
                    count += len(left)-l
            result += right[r:]
            result += left[l:]
            return result
        MergeSort(data)
        return count%1000000007

	

看都看了,再复习一下归并排序!

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

图和名词解释都来自博客!https://www.cnblogs.com/chengxiao/p/6194356.html

这个图好看容易理解分治! 

分治法简单来说就是分而治之,化繁为简,将大问题分解成子问题逐一求解。 在利用分治法寻找 n 个数中第 k 小的元素时,首先在当前数组中随意选中一个基准元素 pivot,然后使用双指针“区域划分”的思想将数组划分为两部分,左半区域的元素比 pivot 小,右半区域的元素比 pivot 大。假设 pivot 基准元素的下标是 pivotIndex,pivot 元素就是整个数组中第 pivotIndex + 1 小的元素。令左半区域的元素个数为 leftNum,若 k == leftNum + 1 则直接返回基准元素;若 k < leftNum + 1 则递归左半部分区域继续找到第 k 小的元素;若 k > leftNum + 1 ,则递归右半部分区域找第 k - (leftNum + 1) 小的元素 [^1]。 在排列组合问题中,设集合 R = {r1, r2, ..., rn} 是要进行排列的 n 个元素,其中 r1, r2, ..., rn 可能相同,也可使用分治法来列出 R 的所有不同排列,即给定 n 以及待排的 n 个可能重复的元素,计算输出 n 个元素的所有不同排列 [^2]。 以下是一个使用分治法寻找第 k 小元素的 Python 代码示例: ```python def find_kth_smallest(arr, k): if len(arr) == 1: return arr[0] pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] leftNum = len(left) if k == leftNum + 1: return pivot elif k < leftNum + 1: return find_kth_smallest(left, k) else: return find_kth_smallest(right, k - (leftNum + len(middle))) arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5] k = 3 result = find_kth_smallest(arr, k) print(f"第 {k} 小的元素是: {result}") ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值