class MergeSort:
# 归并排序,本质上是递归,先左边有序,右边有序,然后merge一下
def merge_sort(self, arr):
if arr == None or len(arr) < 2:
return
self.process(arr, 0, len(arr)-1)
def process(self, arr, l, r):
if l == r:
return
mid = l + ((r-l) >> 2)
self.process(arr, l, mid)
self.process(arr, mid+1, r)
self.merge(arr, l, mid, r)
def merge(self, arr, l, mid, r):
help_ = [0 for i in range(r-l+1)]
i = 0
p1 = l
p2 = mid+1
# p1和p2都不越界的情况下,如果相等,先拷贝左边
while p1 <= mid and p2 <= r:
if arr[p1] <= arr[p2]:
help_[i] = arr[p1]
i += 1
p1 += 1
else:
help_[i] = arr[p2]
i += 1
p2 += 1
while p1 <= mid:
help_[i] = arr[p1]
i += 1
p1 += 1
while p2 <= r:
help_[i] = arr[p2]
i += 1
p2 += 1
for i in range(len(help_)):
arr[l+i] = help_[i]
# 非递归方法
def merge_sort2(self, arr):
if arr == None or len(arr) < 2:
return
n = len(arr)
mergeSize = 1 # 当前有序的左组长度
while mergeSize < n:
l = 0
while l < n:
# l...m 左组 大小为mergeSize
m = l + mergeSize -1
if m >= n:
break
r = min(m+mergeSize, n-1)
self.merge(arr, l, m, r)
l = r+1
# 防止溢出,如果mergeSize > n/2,下一句mergeSize = mergeSize << 1,则mergeSize一定>n
# 所以先判断mergeSize > n/2,如果成立,就不用再去乘2了
if mergeSize > n/2:
break
mergeSize = mergeSize << 1 # 位运算就是快
关于小和问题,你求一个属左边比它小的数的总和,等同于:当前数,右边有几个数比它大,那么就要加几次这个数。举例,比1大的右边的数有4个,那个求数组小和的时候,一定有4个1相加。
求数组小和实际上就是一个merge的过程
class SmallSum:
def small_sum(self, arr):
if arr == None or len(arr) < 2:
return 0
self.process(arr, 0, len(arr)-1)
def process(self, arr, l, r):
if l == r:
return
# l < r
mid = l + ((r-l) >> 2)
# 左侧小和+右侧小和+整体小和
return self.process(arr, l, mid) + self.process(arr, mid+1, r) + self.merge(arr, l, mid, r)
def merge(self, arr, l, mid, r):
help_ = [0 for i in range(r-l+1)]
i = 0
p1 = l
p2 = mid+1
res = 0
while p1 <= mid and p2 <= r:
if arr[p1] < arr[p2]:
res += (r-p2+1)*arr[p1]
help_[i] = arr[p1]
i += 1
p1 += 1
else:
res += 0
help_[i] = arr[p2]
i += 1
p2 += 1
while p1 <= mid:
help_[i] = arr[p1]
i += 1
p1 += 1
while p2 <= r:
help_[i] = arr[p2]
i += 1
p2 += 1
for i in range(len(help_)):
arr[l+i] = help_[i]
return res
求解降序对也可以用到归并排序
归并排序的应用场景
1.每一个数,右边有多少个数比你大,整体数量
2.每一个数,右边有多少个数比你小,整体数量
3.每一个数,左边有多少个数比你大,整体数量
4.每一个数,左边有多少个数比你小,整体数量