在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數p。並將p對1000000007取模的結果輸出。 即輸出p%1000000007
題目保證輸入的陣列中沒有的相同的數字
資料範圍:
對於%50的資料,size<=10^4
對於%75的資料,size<=10^5
對於%100的資料,size<=2*10^5
示例1複製
1,2,3,4,5,6,7,0
複製
7
方法一:暴力
# -*- coding:utf-8 -*-
class solution:
def inversepairs(self, data):
# write code here
count=0
n=len(data)
for i in range(n-1):
for j in range(1+i,n):
if data[i]>data[j]:
count+=1
return count
方法二:索引
import copy
def inversepairs(data):
count = 0
copys = copy.copy(data)
# copys=data[:]
# copys = copy.deepcopy(data)
copys.sort()
for i in range(len(copys)):
count += data.index(copys[i])
print('count=',count)
data.remove(copys[i])
return count
# return count%1000000007
a=[1,2,3,5,6,7,4]
print(inversepairs(a))
方法三:歸併
class solution:
def reversepairs(self, nums: list[int]) -> int:
def f(l,r):
if l>=r:
return 0
mid=(l+r)//2
s=f(l,mid)+f(mid+1,r)
i=lj=mid+1
pos=l
res=
while i<=mid and j<=r:
if nums[i]<=nums[j]:
dp[pos]=nums[i]
i+=1
else:
dp[pos]=nums[j]
j+=1
s=s+(mid-i+1)
pos+=1
for k in range(i,mid+1):
dp[pos]=nums[k]
pos+=1
for k in range(j,r+1):
dp[pos]=nums[k]
pos+=1
nums[l:r+1]=dp[l:r+1]
return s
l=len(nums)
dp=[0]*l
return f(0,l-1)
class solution:
def inversepairs(self, data):
# write code here
# 思路:歸併排序。分為兩個部分,尋找兩個部分內部的逆序列,再尋找兩個部分之間交叉的逆序列。
if not data:
return 0
# 由於必須保證有兩個列表,兩個位址,因此不能直接用assist=data
assist = [i for i in data]
return self.merge(data, assist, 0, len(data) - 1) % 1000000007
# 每乙個新的遞迴開始時,都是要大範圍重新排序的,這個範圍會覆蓋所有以前遞迴過的片段,因此data和assist可以互換,因為上一次排好序的列表只在下一次的比較時需要使用,而不需要遞延到下一次的輔助列表中。
def merge(self, data, assist, low, high):
# 判斷終止條件:如果子部分裡面只剩下1個數,此時low=high,不用比較,返回0
if low == high:
assist[low] = data[low] # 由於assist和data互換了,因此如果遞迴到最小單位,要按照上次算出的排序方式排序
return 0
mid = (low + high) / 2
left = self.merge(assist, data, low, mid)
right = self.merge(assist, data, mid + 1, high)
# 開始歸併排序
count = 0
i = mid
j = high
k = high # k為assist列表的索引
# 從後往前進行遍歷,對左子列和右子列中的數進行比較大小
while i >= low and j > mid:
# 如果左子列最後乙個數大於右子列最後乙個數,表示左子列大於右子列所有的數
if data[i] > data[j]:
count += j - mid # count要加上右子列中剩下元素的個數
assist[k] = data[i] # 將最大的數存入輔助列表
i -= 1 # 最大數已被排序,將左子列向前遍歷乙個元素
# 如果左子列最後乙個數小於等於右子列最後乙個數,不構成逆序對
else:
assist[k] = data[j] # 將最大的數存入輔助列表
j -= 1 # 最大數已被排序,將右子列向前遍歷乙個元素
k -= 1
# 上面乙個while中還會剩下最後乙個元素沒有被排序,進入assist
while i >= low:
assist[k] = data[i]
i -= 1
k -= 1
while j > mid:
assist[k] = data[j]
j -= 1
k -= 1
return left + right + count # 返回當前左右子列計算出的逆序對數量,加上左右子列內部的逆序對數量
陣列中逆序對
題目 在陣列中的兩個數字,如果前面的乙個數字大於後面的數字,則這兩個數字為乙個逆序對。輸入乙個陣列,求這個陣列的逆序對個數。例如 給定陣列 則有 5,3 5,1 8,3 8,1 3,1 這5個逆序對。問題分析 我採用兩種方法來解決這個問題 1 考慮到二叉搜尋樹中每個節點x,它的左子樹所有關鍵字的值小...
陣列中的逆序對
來自劍指offer 分析 我們第一反應是順序掃瞄整個陣列,每掃瞄到乙個數字時,逐個比較該數字和它後面的數字的大小。如果後面的數字比它小,則這個兩個數字就組成了乙個逆序對。假設陣列有n個數字,由於每個數字都要和o n 個數字作比較,因此這個演算法的時間複雜度為o n 2 換思路 我們採用歸併思想,先考...
陣列中的逆序對
題目 在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。用歸併排序演算法,歸併的時候,從後向前歸併。include using namespace std int getreversenum int p1,int p2,int...