题目 :在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
直接两次遍历是不行的,时间肯定会超。这里用到了归并排序中归并这一步的思想,来求逆序对。
浏览答案中会发现两个代码极为相似的,但是第二个代码多了一句
困扰许久,wdtmd我是真的蠢
from typing import List
class Solution:
def mergeSort(self, nums, tmp, l, r):
if l >= r:
return 0
mid = (l + r) // 2
inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r)
i, j, pos = l, mid + 1, l
while i <= mid and j <= r:
if nums[i] <= nums[j]:
tmp[pos] = nums[i]
i += 1
inv_count += (j - (mid + 1))
else:
tmp[pos] = nums[j]
j += 1
pos += 1
for k in range(i, mid + 1):
tmp[pos] = nums[k]
inv_count += (j - (mid + 1))
pos += 1
for k in range(j, r + 1):
tmp[pos] = nums[k]
pos += 1
nums[l:r+1] = tmp[l:r+1]
return inv_count
def reversePairs(self, nums: List[int]) -> int:
n = len(nums)
tmp = [0] * n
return self.mergeSort(nums, tmp, 0, n - 1)
a = Solution().reversePairs([7,5,4,6])
print(a)
from typing import List
class Solution:
def reversePairs(self, nums: List[int]) -> int:
self.cnt = 0
def merge(nums, start, mid, end):
i, j, temp = start, mid + 1, []
while i <= mid and j <= end:
if nums[i] <= nums[j]:
temp.append(nums[i])
i += 1
else:
self.cnt += mid - i + 1
temp.append(nums[j])
j += 1
while i <= mid:
temp.append(nums[i])
i += 1
while j <= end:
temp.append(nums[j])
j += 1
for i in range(len(temp)):
nums[start + i] = temp[i]
def mergeSort(nums, start, end):
if start >= end: return
mid = (start + end) >> 1
mergeSort(nums, start, mid)
mergeSort(nums, mid + 1, end)
merge(nums, start, mid, end)
mergeSort(nums, 0, len(nums) - 1)
return self.cnt
a = Solution().reversePairs([7,5,6,4])
print(a)
困扰的地方就是对count这部分的加法,官方出现了两次,另一作者是一次,解析如下:
对于归并的两个数组[i,mid], [mid+1,j]
官方解法是当第一个子数组中的数字A进入到temp数组中的时候,那么这个时候第二个数组中下标指针前面的数就都比这个A要小,因为他们已经进入了temp,所以加。
然后当while i <= mid and j <= r:这个判定不成立的时候,如果第一个数组还有没进入temp的,那么同理,右边数组里面剩下的肯定都比这个小。
另外作者解法只有在while i <= mid and j <= end:且if nums[i] <= nums[j]都不成立时候才加count,他的意思是当左边数组当前数字A比右边数组当前数字B大的时候,那么这时候就说明,第一个数组中A右边的数字都比B大(因为两个子数组都是有序的),所以加mid - i + 1,如果while i <= mid and j <= end这个判定已经不成立了,那么如果左边数组还有数字,那么说明右边的数组都加到temp了,每次右边数字加进去的时候都会计算,不会遗漏;如果右边数组还有数字,那么这些数字都比左边的大了,也不用加count。