【剑指offer】数组中的逆序对(python)
思路:先把数组分割成子数组,先统计出子数组内部的逆序对数目,然后统计出两个相邻子数组之间的逆序对数目。统计过程中,还需要对数组进行排序,以免重复统计。
两个指针分别指向两个子数组的末尾,如果第一个子数组的数字大于第二个数组的数字,构成逆序对,并且逆序对数目等于第二个子数组中剩余数字个数,每一次比较都把较大数字从后往前复制到辅助数组中。
# -*- coding:utf-8 -*- class Solution: tmp = [] cnt = 0 def InversePairs(self, data): # write code here self.tmp = [-1 for i in range(len(data))] self.mergeSort(data, 0 , len(data)-1) return int(self.cnt % 1000000007) def mergeSort(self, data, l, h): if h - l < 1: return m = (h+l)//2 self.mergeSort(data, l, m) self.mergeSort(data, m+1, h) self.merge(data, l, m, h) def merge(self, data, l, m, h): i = l j = m + 1 k = l while i <= m or j <= h: if i > m: self.tmp[k] = data[j] j+=1 elif j > h: self.tmp[k] = data[i] i+=1 elif data[i] <= data[j]: self.tmp[k] = data[i] i+=1 else: self.tmp[k] = data[j] j += 1 self.cnt += (m - i + 1) # nums[i]>nums[j],说明nums[i...m]都大于nums[i] k += 1 for m in range(l, h+1): data[m] = self.tmp[m]
归并排序的代码,关键在于处理左边+处理右边+归并,归并中关键在于辅助数组,使用temp中的元素覆盖nums中元素。
class Solution(object): def sortArray(self, nums): """ :type nums: List[int] :rtype: List[int] """ length = len(nums) start = 0 end = length - 1 return self.sort(nums, start, end) def sort(self, nums, low, high): mid = (low + high) // 2 if low < high: # 处理左边 self.sort(nums, low, mid) # 处理右边 self.sort(nums, mid+1, high) # 左右归并 self.merge(nums, low, mid, high); return nums def merge(self,nums, low, mid, high): tmp = [-1 for i in range(high - low + 1)] i = low j = mid+1 k = 0 # 找出较小值元素放入temp数组中 while i<=mid and j<=high: if nums[i] <= nums[j]: tmp[k]=nums[i] k+=1 i+=1 else: tmp[k]=nums[j] k+=1 j+=1 # 处理较长部分 while i<=mid: tmp[k] = nums[i] k+=1 i+=1 while j<=high: tmp[k] = nums[j] k+=1 j+=1 # 使用temp中的元素覆盖nums中元素 for k2 in range(len(tmp)): nums[k2+low] = tmp[k2]