题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1: 输入: [7,5,6,4] 输出: 5
解题思路1: 暴力破解(超时)
暴力破解法, 我们直接从后往前双重遍历数组, 看后面元素是否小于前边元素, 记录count+1. 遍历完成后就可以拿到数据. 因为时间复杂度为 O(n^2), 所以会超时
示例代码1:
def reversePairs2(self, nums: [int]) -> int:
res = 0
l = len(nums) - 1
for i in range(0, l + 1):
for j in range(i + 1, l + 1):
print(nums[l - i], nums[l - j])
if nums[l - i] < nums[l - j]:
res += 1
return res
解题思路2: 归并排序法
- 因为归并排序会先将数组按前后顺序分割为左右两个部分进行递归, 利用归并排序的思路, 当在分治完成后进行合并时, 是将左右2个有序的数组合并成一个新的有序数组. 在这个合并的过程中我们就可以逆序对的计算
- 当左边数组(靠前元素) 中的A个元素大于右边数组(靠后元素)的B元素时, 因为2个数组都是有序的, 所以 A元素后的所有元素都大于B元素, 这时, 我们就得到了 左边数组A及A之后的N个元素与B元素组成的逆序对
- 根据步骤2, 我们在归并的过程中一直计算, 最终就能得到所有的逆序对
示例代码2:
def reversePairs(self, nums: [int]) -> int:
def mergeSort(arr):
if len(arr) <= 1:
return arr
else:
mid = int(len(arr) / 2)
left = mergeSort(arr[:mid])
right = mergeSort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = 0
j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
# 步骤2: 在合并的过程中判断逆序对
self.count += len(left) - i
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
self.count = 0
mergeSort(nums)
return self.count