刷到归并,就此开坑,归并似乎用的是分治的思维
👉图解归并算法
👉参考详解 :其中诠释出,通过分治的方法,降低对比交换的次数,来降低时间复杂度
分治!就是把大问题肢解成同类小问题解决(递归)
二分法查询(用于有序数列)
通过设立center,把长数列中查询或计数的工作分到每一个部分当中去完成,最后合并(求和)
代码略
归并排序
def mergeSort(temp_list, number_list, left, right):
if left == right:
return
elif left < right:
center = (left + right)//2
mergeSort(temp_list, number_list, left, center)
mergeSort(temp_list, number_list, center+1, right)
merge(temp_list, number_list, left, center, right)
return number_list
pass
def merge(temp_list, number_list, left, center, right):
idx_l = left
idx_r = center + 1
idx_ct = 0
while idx_r <= right:
if number_list[idx_r] >= number_list[idx_l]:
temp_list[idx_ct] = number_list[idx_l]
idx_l += 1
idx_ct += 1
pass
else:
temp_list[idx_ct] = number_list[idx_r]
idx_r += 1
idx_ct += 1
if idx_l > center:
while idx_r <= right:
temp_list[idx_ct] = number_list[idx_r]
idx_r += 1
idx_ct += 1
while idx_l <= center:
temp_list[idx_ct] = number_list[idx_l]
idx_l += 1
idx_ct += 1
for i in range(idx_ct):
number_list[left+i] = temp_list[i]
for i in range(len(temp_list)):
temp_list[i] = 0
pass
def testMergesort():
number_list = [364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]
temp_list = [0 for i in range(len(number_list))]
print(mergeSort(temp_list, number_list, 0, len(number_list)-1))
testMergesort()
输出为:[3, 38, 45, 64, 67, 80, 82, 115, 142, 144, 147, 149, 162, 174, 181, 187, 219, 221, 233, 234, 235, 256, 259, 266, 267, 268, 275, 284, 288, 301, 315, 341, 355, 360, 364, 366, 380, 401, 406, 407, 416, 418, 425, 433, 446, 455, 460, 463, 465, 474, 478, 486, 497, 505, 516, 523, 550, 557, 569, 571, 575, 576, 583, 588, 601, 604, 630, 637, 648, 650, 655, 665, 667, 671, 697, 727, 735, 739, 746, 747, 773, 784, 795, 811, 848, 849, 863, 870, 874, 882, 930, 935, 936, 958, 965, 971, 973, 983, 993, 995]
* merge函数还可以做重构
逆序对应用
逆序对指的是在一串数字中前大后小的数字对。归并的交换不重复,交换次数就可以用来统计逆序对的数量。
与排序的差别在于多了计数
写的时候一定要注意count的计数的位置,以及left和right的限制!
def InversePairs(data):
# write code here
temp = [0 for i in range(len(data))]
count = mergeCount(data, temp, 0, len(data) - 1)
print(temp)
return count
def mergeCount(data, temp, left, right):
count = 0
if left == right:
return 0
center = (left + right) // 2
count += mergeCount(data, temp, left, center)
count += mergeCount(data, temp, center + 1, right)
idx_l = left
idx_r = center + 1
idx_ct = 0
while idx_r <= right and idx_l <= center:
if data[idx_r] >= data[idx_l]:
temp[idx_ct] = data[idx_l]
idx_ct += 1
idx_l += 1
pass
else:
count += center + 1 - idx_l
temp[idx_ct] = data[idx_r]
idx_ct += 1
idx_r += 1
pass
pass
while idx_r <= right:
temp[idx_ct] = data[idx_r]
idx_ct += 1
idx_r += 1
pass
while idx_l <= center:
temp[idx_ct] = data[idx_l]
idx_ct += 1
# count += center + 1 - idx_l
idx_l += 1
pass
for i in range(idx_ct):
data[left + i] = temp[i]
pass
return count
def testInversePairs():
data = [364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]
print(InversePairs(data))
输出为:正常排序如上
逆序数为:2519