参考:https://www.jianshu.com/p/b661d3e802f9
数组类问题两种思路:
思路一: T ( i , j ) = T ( i , j − 1 ) + C T(i,j) = T(i,j-1)+C T(i,j)=T(i,j−1)+C
思路二: T ( i , j ) = T ( i , m ) + T ( m , j ) + C T(i,j) = T(i,m)+T(m,j)+C T(i,j)=T(i,m)+T(m,j)+C
使用思路一,每次统计[0,j-1]中大于2*a[j]的元素个数
Naive方法 O ( n 2 ) O(n^2) O(n2)
使用BST,不过要写平衡树,有点麻烦
使用的也是思路一,首先复制一个排序的数组 B = [ b 1 , . . . , b n ] B=[b_1,...,b_n] B=[b1,...,bn],从大到小排
树状数组中的 A [ i ] A[i] A[i]对应的是元素 b i b_i bi是否已出现
那么C[i]对应的是大于等于i的元素出现了多少个
当遍历到原始数组的第j个元素时,序号比它小的元素都出现过了
假如maxi是大于2*nums[j]的最大元素【这可以用二分查找找】
那么明显与nums[j]相关的逆序对数为 C [ m a x i ] C[maxi] C[maxi]
可见,树状数组在统计【小于/大于某个值的元素的和】上有妙用
class Solution(object):
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
import copy
A = list(sorted(copy.deepcopy(nums),reverse=True))
n = len(A)
c = [0]*n
ans = 0
def lowbit(k):
return -k&k
def add(k, d): # k>=1
while k<=n:
c[k - 1] += d
k += lowbit(k)
def sum(k): # k>=1
res = 0
while k>=1:
res += c[k-1]
k -= lowbit(k)
return res
def bs(ele):
l = 0
r = n
while r-l>1:
mid = (r+l)>>1
if A[mid]>=ele:
l = mid
else:
r = mid
if A[l]>=ele:
return l
else:
return -1
for ele in nums:
index = bs(2*ele+1)
if index!= -1:
ans += sum(index+1)
add(bs(ele)+1, 1)
return ans
归并是思路二,注意检查逆序对的时机
整个循环里用一个统一的指针,这样不需要每次都检查
要么在每放一个nums[i]时对nums[j]检查(加的值与j无关),要么在每放一个nums[j]时对nums[i]检查(加的值与i无法)
归并排序版:
class Solution(object):
def merge(self, l, r):
if r-l<=1:
return
mid = (r+l)>>1
self.merge(l,mid)
self.merge(mid, r)
c = []
i=l
j=mid
pointer_j = mid
while i<mid:
while pointer_j<r and self.nums[pointer_j]*2<self.nums[i]:
pointer_j += 1
self.ans += pointer_j-mid
while j<r and self.nums[i]>self.nums[j]:
c.append(self.nums[j])
j += 1
c.append(self.nums[i])
i += 1
while j < r:
c.append(self.nums[j])
j += 1
self.nums = self.nums[:l]+c+self.nums[r:]
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
self.nums = nums
self.ans = 0
self.merge(0,len(nums))
return self.ans
实际在leetcode里跑的时候自己排序好像会超时= =,可能是临时数组的操作太浪费时间了,还不如让python排序
class Solution(object):
def merge(self, lis):
if len(lis)<=1:
return lis
mid = len(lis)>>1
a = self.merge(lis[0:mid])
b = self.merge(lis[mid:len(lis)])
r = len(b)
ptr = 0
for ele in a:
while ptr < r and ele > 2 * b[ptr]:
ptr += 1
self.ans += ptr
lis.sort()
return lis
def reversePairs(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
self.nums = nums
self.ans = 0
self.merge(nums)
return self.ans