493. 翻转对
题干越简单,题目越难。
本题主要是卡时间复杂度,暴力双循环O(n²)一看提交通过率就知道没戏,因此考虑O(nlogn)的解法
归并排序,如果能在归并排序的基础上进行翻转对统计,可以满足时间复杂度。
我在第一次排序的时候,将排序规则定为left[i] > right[j] *2,这样会使数组乱序,因此考虑在正常排序的基础上,在外围进行翻转数统计。
class Solution:
def reversePairs(self, nums: List[int]) -> int:
self.ans = 0
def mergesort(List):
if len(List)<2:
return List
mid = len(List)>>1
left,right = mergesort(List[:mid]),mergesort(List[mid:])
i,j = 0,0
return merge(left,right)
def merge(left,right):
l,r=0,0
result=[]
while(l<len(left) and r<len(right)):
if(left[l]>right[r]):
result.append(left[l])
l+=1
else:
result.append(right[r])
r+=1
result+=left[l:]
result+=right[r:]
return result
mergesort(nums)
return self.ans
上述是正常的排序代码,只需要在mergesort的return merge(left,right)前统计一次翻转对即可,这里用到的思想是:
数组降序排列,维护两个指针,分别指向左右数组的第一个数,不断判断是否满足left[i] > right[j]*2,如果不满足,则右指针后移,如果满足,则证明从右指针开始到最后一个数,皆满足条件,累加即可
class Solution:
def reversePairs(self, nums: List[int]) -> int:
self.ans = 0
def mergesort(List):
if len(List)<2:
return List
mid = len(List)>>1
left,right = mergesort(List[:mid]),mergesort(List[mid:])
i,j = 0,0
while(j<len(right) and i<len(left)):
if left[i] <= 2*right[j]:
j += 1
else:
self.ans += len(right)-j
i += 1
return merge(left,right)
def merge(left,right):
l,r=0,0
result=[]
while(l<len(left) and r<len(right)):
if(left[l]>right[r]):
result.append(left[l])
l+=1
else:
result.append(right[r])
r+=1
result+=left[l:]
result+=right[r:]
return result
mergesort(nums)
return self.ans