爽歪歪666
不以物喜,不以己悲,努力才是永恒的主题。

题目

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

分析

蛮力法:

顺序扫描整个数组,每扫描到一个数字,逐个比较该数字后面的数字的大小,如果比它小,则两个数字组成一个逆序对,假设有n个数字,每个数字都要和O(n)个数字进行比较,因此这种算法的时间复杂度是O(n2

归并排序法

先把数组分割成子数组,统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还要对数组排序 。

归并排序编程实现

 1 def mergeSort(lsts):
 2     """
 3     归并排序:分治思想,与输入数据的顺序无关,但需要额外的内存空间
 4     如何划分小集合:
 5     折半划分,一分二,二分四,直到每个小集合里面元素为1个,再原路归并
 6     如何将两个有序小集合合并为一个有序大集合(类似于合并两个递增的链表,结果仍是递增):
 7     1.创建一个额外大集合用于存储归并结果,长度是两个小集合之和
 8     2.从左到右逐一比较两个小集合中的元素,把较小的元素优先放入大集合
 9     :param lsts:
10     :return:
11     """
12     if len(lsts)<2:
13         return lsts
14     mid = len(lsts)>>1 # 右移相当于除2
15     left = lsts[0:mid]
16     right = lsts[mid:]
17     return merge(mergeSort(left),mergeSort(right))
18 
19 def merge(left ,right):
20     arr=[]
21     while left and right:
22         if left[0]< right[0]:
23             arr.append(left.pop(0))
24         else:
25             arr.append(right.pop(0))
26     if not left:
27         arr.extend(right)
28     if not right:
29         arr.extend(left)
30     return arr
1 if __name__ == '__main__':
2     lsts =[3,5,38,15,36,27,2,99,50]
3     print(mergeSort(lsts))
4    

逆序对代码实现

 1 class InversePairs():
 2     def __init__(self):
 3         self.count = 0
 4     def mergeSort(self,numset):
 5         """
 6         求逆序对
 7         """
 8         if len(numset)<2:
 9             return numset
10         mid = len(numset)>>1
11         left = numset[0:mid]
12         right = numset[mid:]
13         sorted_arr =self.merge(self.mergeSort(left), self.mergeSort(right))
14         return sorted_arr # 在此不能直接返回两个,return self.cout,sorted_arr,返回的则是元组
15 
16     def merge(self,left ,right):
17         arr=[]
18         i =0
19         j =0
20         while i<len(left) and j<len(right):
21             # print(left)
22             # print(right)
23             if left[i] <= right[j]:
24                 arr.append(left[i])
25                 i += 1
26             else:
27                 arr.append(right[j])
28                 j += 1
29                 self.count += len(left)-i # 第i个大于right[i],则从第i个起,后面都大于right[i],所以加上len(left)-i
30         # left,right有一个为空时
31         if left[i:]:
32             arr.extend(left[i:])
33         if right[j:]:
34             arr.extend(right[j:])
35         return arr
36     def inversePairs(self,numset):
37         if len(numset)<2:
38             return self.count
39         self.mergeSort(numset)
40         return self.count %1000000007
41 if __name__ == '__main__':
42     numset=[7,5,6,4]
43     inverse= InversePairs()
44     print(inverse.inversePairs(numset))

 

posted on 2020-04-20 19:28  爽歪歪666  阅读(163)  评论(0编辑  收藏  举报