各种排序算法:
归并排序:
时间复杂度:每层扫描
O
(
n
)
O(n)
O(n),划分为
l
o
g
2
n
log_{2}n
log2n层,
O
(
l
o
g
n
)
O(logn)
O(logn),因此总的时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
稳定:重复数字相对位置不变
思想:
- 确定分界点
- 一分为二:将数组一分为二,一个无序的数组成为两个有序的数组
- 合二为一:将两个有序数组合并成为一个有序数组
python 模版
def merge_sort(nums):
if len(nums) <= 1:
return 0
# 确定分界点
mid = len(nums) // 2
# 一分为二,左右递归排序
L = nums[:mid]
R = nums[mid:]
merge_sort(L), merge_sort(R)
# 双路归并,合二为一
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] <= R[j]:
nums[k] = L[i]
k += 1
i += 1
else:
nums[k] = R[j]
k += 1
j += 1
while i < len(L): # 左边没循环完,加在后边
nums[k] = L[i]
k += 1
i += 1
while j < len(R): # 右边没循环完,加在后边
nums[k] = R[j]
k += 1
j += 1
if __name__ == "__main__":
n = int(input())
nums = list(map(int, input().split()))
merge_sort(nums)
print(','.join(map(str, nums)))
5
3 1 2 5 4
1,2,3,4,5
以下模版在需要左右边界时候再用,一般用上述模版。
"""利用辅助数组,空间复杂度O(n)"""
def merge_sort(q, l, r):
if l >= r: return # 当前区间最多只有一个数
# 确定分界点
mid = l + r >> 1
# 递归左右排序
merge_sort(q, l, mid)
merge_sort(q, mid + 1, r)
# 双路归并,合二为一
k, i, j = 0, l, mid + 1
temp = []
while i <= mid and j <= r:
if q[i] < q[j]:
temp.append(q[i])
i += 1
else:
temp.append(q[j])
j += 1
while i <= mid: # 左边没循环完,加在后边
temp.append(q[i])
i += 1
while j <= r: # 右边没循环完,加在后边
temp.append(q[j])
j += 1
i = l
for x in temp: # 把结果重新放回q数组
q[i] = x
i += 1
应用:逆序对的数量
来源:
1. Acwing
2.《剑指offer》面试题51:数组中的逆序对
题目描述:
给定一个长度为n的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i < j 且 a[i] > a[j],则其为一个逆序对;否则不是。
输入格式
第一行包含整数n,表示数列的长度。
第二行包含 n 个整数,表示整个数列。
输出格式
输出一个整数,表示逆序对的个数。
数据范围
1≤n≤100000
输入样例:
6
2 3 4 5 6 1
输出样例:
5
算法1 (归并排序)
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
Python 代码
"""
求逆序对的数目
利用归并排序的思想
"""
def merge_sort(nums):
if len(nums) <= 1:
return 0
mid = len(nums) // 2
L = nums[:mid]
R = nums[mid:]
res = merge_sort(L) + merge_sort(R) # 统计左区间和右区间的逆序对数量
# 归并的过程
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] <= R[j]:
nums[k] = L[i]
k += 1
i += 1
else:
nums[k] = R[j]
res += len(L) - i # 统计跨区间的逆序对数量
k += 1
j += 1
while i < len(L):
nums[k] = L[i]
k += 1
i += 1
while j < len(R):
nums[k] = R[j]
k += 1
j += 1
return res # 返回逆序对个数
if __name__ == "__main__":
n = int(input())
nums = list(map(int, input().split()))
print(merge_sort(nums))
输入
6
2 3 4 5 6 1
输出
5