面试题51. 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
解答:
根据之前的经验可知 此题使用归并排序解答。
1 归并使用双封闭的二分[ l ,m ] [ m+1 , r ],即能取到最右端的值,初始带入r = len-1.
2 归并终止条件为 l<r, 终止点位l=r。
3 排序中的while循环终止条件为 i<=len and j<=len,因为经历过一次比较以后,i 或者j自增,到达了i或者j数组的边界,这时index是超出数组的,但是仍然需要进行一轮循环,将最后的部分直接extend上。
4 排序中 在满足 arr_l[i] > arr_r[j]的地方进行**+左边现存数的个数**,即为len-i。当达到边界时不需要加和 因为之前已经全部计数。
5 记住 i j到达边界时的break!
代码:
class Solution:
def reversePairs(self, nums) -> int:
global res
res = 0
self.merge(nums, 0, len(nums) - 1)
return res
def merge(self, arr, l, r):
if l < r:
mid = (l + r) // 2
self.merge(arr, l, mid)
self.merge(arr, mid + 1, r)
self.sort(arr, l, r,mid)
def sort(self, arr, l, r, m):
arr_l = arr[l:m + 1]
arr_r = arr[m + 1:r + 1]
new = []
i = 0
j = 0
#print(arr_l,arr_r,l,m,m+1,r)
while i <= m - l + 1 and j <= r - m:
#print(i,j,m-l+1,r-m+1)
global res
if i == m - l+1:
new.extend(arr_r[j:])
break
elif j == r - m:
new.extend(arr_l[i:])
# global res
#print(m-l+1-i,'1111111')
#res += (m - l - i)
break
elif arr_l[i] > arr_r[j]:
new.append(arr_r[j])
#print(j+1,'2222222222')
res += (m-l-i+1)
j += 1
else:
new.append(arr_l[i])
i += 1
#print(res,'##')
arr[l:r + 1] = new
TIPS:
1 归并二分的 双闭区间 l<r终止条件
2 while循环的 and 以及 均为<=len
3 边界处的break
4 逆序对count的思想