本文介绍了归并算法的应用,小和问题和数组的逆序对解法一样。
小和问题
在一个数组中,每一个数的左边比其小的元素累加起来,叫做这个数组的小和。
例如,[1,3,2,4,5]
对于3,前面比它小的数有1
对于2,前面比它小的数有1
对于4,前面比它小的数有1,3,2
对于5,前面比它小的数有1,3,2,4
因此,该数组的小和为1+1+1+(1+3+2)+(1+3+2+4)=19
解法:
利用归并排序思想,只是多了ans += (R - j + 1)*data[i]
这么一行记录小和。
代码如下:
def merge(data, L, mid, R):
i = L
j = mid + 1
helper = []
ans = 0
while i <= mid and j <= R:
if data[i] < data[j]:
ans += (R - j + 1) * data[i]
helper.append(data[i])
i += 1
else:
helper.append(data[j])
j += 1
if i <= mid:
helper.extend(data[i:mid + 1])
else:
helper.extend(data[j:R + 1])
data[L:R + 1] = helper
return ans
def mergesort(data, L, R):
if L == R:
return 0
mid = (L + R) // 2
return mergesort(data, L, mid) + mergesort(data, mid + 1, R) + merge(data, L, mid, R)
def SmallSum(data):
# write code here
if not data:
return 0
return mergesort(data, 0, len(data) - 1)
数组的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。
解法:
与上题区别在于,上题是求顺序对,该题是求逆序对,因此由归并按顺序排序改为逆序即可。只需修改data[i] > data[j]
。
def merge(data, L, mid, R):
i = L
j = mid + 1
helper = []
ans = 0
while i <= mid and j <= R:
if data[i] > data[j]:
ans += R - j + 1
helper.append(data[i])
i += 1
else:
helper.append(data[j])
j += 1
if i <= mid:
helper.extend(data[i:mid + 1])
else:
helper.extend(data[j:R + 1])
data[L:R + 1] = helper
return ans
def mergesort(data, L, R):
if L == R:
return 0
mid = (L + R) // 2
return mergesort(data, L, mid) + mergesort(data, mid + 1, R) + merge(data, L, mid, R)
def InversePairs(data):
if not data:
return 0
return mergesort(data, 0, len(data) - 1)
InversePairs([1,3,2,4]