陣列中的逆序對
class
solution
:def
reversepairs
(self, nums: list[
int])-
>
int:
self.cnt =
0def
merge
(nums, start, mid, end, temp)
: i, j = start, mid +
1while i <= mid and j <= end:
if nums[i]
<= nums[j]:)
i +=
1else
: self.cnt += mid - i +1)
j +=
1while i <= mid:
) i +=
1while j <= end:
) j +=
1for i in
range
(len
(temp)):
nums[start + i]
= temp[i]
temp.clear(
)def
mergesort
(nums, start, end, temp)
:if start >= end:
return
mid =
(start + end)//2
mergesort(nums, start, mid, temp)
mergesort(nums, mid +
1, end, temp)
merge(nums, start, mid, end, temp)
mergesort(nums,0,
len(nums)-1
,)return self.cnt
歸併排序的關鍵是並,並的過程中對兩個有序陣列進行合併,合併的過程中能夠計算逆序對的個數。
計算右側小於當前元素的個數
class
solution
:def
countsmaller
(self, nums)
: size =
len(nums)
if size ==0:
return
if size ==1:
return[0
] temp =
[none
for _ in
range
(size)
] indexes =
[i for i in
range
(size)
] res =[0
for _ in
range
(size)
] self.__helper(nums,
0, size -
1, temp, indexes, res)
return res
def__helper
(self, nums, left, right, temp, indexes, res)
:if left == right:
return
mid = left +
(right - left)//2
# 計算一下左邊
self.__helper(nums, left, mid, temp, indexes, res)
# 計算一下右邊
self.__helper(nums, mid +
1, right, temp, indexes, res)
if nums[indexes[mid]
]<= nums[indexes[mid +1]
]:return
self.__sort_and_count_smaller(nums, left, mid, right, temp, indexes, res)
def__sort_and_count_smaller
(self, nums, left, mid, right, temp, indexes, res)
:# [left,mid] 前有序陣列
# [mid+1,right] 後有序陣列
# 先拷貝,再合併
for i in
range
(left, right +1)
: temp[i]
= indexes[i]
l = left
r = mid +
1for i in
range
(left, right +1)
:if l > mid:
# l 用完,就拼命使用 r
# [1,2,3,4] [5,6,7,8]
indexes[i]
= temp[r]
r +=
1elif r > right:
# r 用完,就拼命使用 l
# [6,7,8,9] [1,2,3,4]
indexes[i]
= temp[l]
l +=
1# 注意:此時前面剩下的數,比後面所有的數都大
res[indexes[i]]+=
(right - mid)
elif nums[temp[l]
]<= nums[temp[r]]:
# [3,5,7,9] [4,6,8,10]
indexes[i]
= temp[l]
l +=
1# 注意:
res[indexes[i]]+=
(r - mid -1)
else
:assert nums[temp[l]
]> nums[temp[r]
]# 上面兩種情況只在其中一種統計就可以了
# [3,5,7,9] [4,6,8,10]
indexes[i]
= temp[r]
r +=
1
同樣是算個數,但是精確到了每個元素的個體,這樣需要索引陣列來記錄每次排序完的元素順序。
class
solution
:def
countsmaller
(self, nums):if
not nums:
return
counts =[0
] sorts =
[nums[-1
]]for i in
range
(len
(nums)-2
,-1,
-1):
ele = nums[i]
l =0 r =
len(sorts)
while l < r:
mid =
(l + r)//2
if sorts[mid]
>= ele:
r = mid
else
: l = mid +
1 index = l
sorts.insert(index,ele)
return counts[::
-1]
更巧妙的方法:開闢乙個陣列,從後往前讀取元素,並使用二分查詢,找出陣列的下限,即小於當前元素的個數。
複習:二分查詢無重複元素版:
mid = (left + right) // 2
其實要邏輯弄清楚:
這裡的right = len(nums) - 1
while left <= right:
mid < element : left = mid + 1
mid > element : right = mid - 1
mid == element : return mid
return -1
二分查詢 上限與下限:
下限:這裡的right = len(nums)
while left < right:
mid >= element: right = mid
mid < element: left = mid + 1
return left
上限:while left < right:
mid <= element: left = mid + 1
mid > element : right = mid
return left
2018暑假第十一題
題目 給定 n 個非負整數 a1,a2,an,每個數代表座標中的乙個點 i,ai 在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別為 i,ai 和 i,0 找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。python 說明 你不能傾斜容器,且 n 的值至少為 2。圖中垂直線代...
歸併演算法 歸併排序
歸併演算法 歸併排序 這周需要用到歸併演算法,於是找了找相關的資料,整理如下 歸併排序 merge sort 是利用 歸併 技術來進行排序。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。兩路歸併演算法 1 演算法基本思路 設兩個有序的子檔案 相當於輸入堆 放在同一向量中相鄰的位置上 r low...
第十一章 外部排序
第十一章 外部排序 第十一章外部排序 一 內容提要 1 外部排序指待排序檔案較大,記憶體一次存放不下,尚需存放在外部介質的檔案的排序。2 為減少平衡歸併中外存讀寫次數所採取的方法 增大歸併路數和減少歸併段個數。3 利用敗者樹增大歸併路數。4 利用置換 選擇排序增大歸併段長度來減少歸併段個數。5 由長...