归并排序(python实现)
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.每一个数,左边有多少个数比你小,整体数量