在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。
递归
#分成两部分,大于和小于当前值的区间进行递归计算
#每次记录后面元素小于当前元素的个数
class Solution:
def InversePairs(self , data: List[int]) -> int:
def find(nums):
if len(nums)<=0:return 0#列表中只有一个元素 逆序对个数=0
pre=nums[0]
da,xiao,res=[],[],0
for i in nums[1:]:
if i>pre:
da.append(i)
else:
res+=1+len(da)#此时da中的值都 >pre 都比它大(包括pre) 记录它带来的逆序个数
xiao.append(i)
return res+find(da)+find(xiao)
return find(data)%1000000007
# #归并排序做法
class Solution:
def InversePairs(self, a):
return self.merge_sort(a,[0]*len(a),0,(len(a)-1))%1000000007;
#[0]*len(a)代表里面有len(a)个0的列表
#因为py自带大数,所以只需要最后取模即可,中间无需取模
def merge_sort(self,a,b,l,r):
if(l>=r):return 0
mid=(l+r)//2 #整数除法
res_l=self.merge_sort(a,b,l,mid)#排序左区间
res_r=self.merge_sort(a,b,mid+1,r)#排序右区间
res_=self.merge(a,b,l,r)#合并左右区间
return res_l+res_r+res_
def merge(self,a,b,l,r):
mid=(l+r)//2#区间中点
i=l#左区间开头指针
j=mid+1#右区间开头指针
k=l#合并后的新数组的头指针
res=0
while i<=mid and j<=r:
if a[i]>a[j]:#左半边的数更大
b[k]=a[j]
k+=1
j+=1
res+=mid-i+1#左半边剩余的数,都比a[j]大,a[j]构成逆序对个数=左半边剩余的数==(右端-左端+1)=(mid-i+1)
else :#左半边的数更小
b[k]=a[i]
k+=1
i+=1
while i<=mid:#左区间还有剩余
b[k]=a[i]
k+=1
i+=1
while j<=r:#右区间还有剩余
b[k]=a[j]
k+=1
j+=1
a[l:r+1]=b[l:r+1]#辅助数组拷贝到原数组
return res