归并排序应用:小数之和

阅读 210

2022-07-04

今天元旦,正儿八经写个面试题解


文章目录

  • ​​Question​​
  • ​​Idea​​
  • ​​Code​​

Question

一个数组,从左到右比该数小的数的和就是该数的小组和,所有数的小数和就是数组的小数和。
求小数和。
例如:
【1,2,4,1】
1的左边没有比他小的 小数和 0
2的左边1比他小 小数和 1
4的左边 1 和 2 比他小 小数和 3
1的左边没有比他小的 小数和 0
数组的小数和为0+1+3+0 = 4

Idea

数从左到右小的数,反过来就是数从右到左大的数
1的右边有 2 4大 =》2 * 1
2的右边有 4 =》2 * 1
4的右边无
1的右边无
结果 2 * 1 + 2 * 1 = 4
归并排序的过程中
是将左部分排好序 右部分排好序 然后左右部分合并
在每次合并的时候,左部分比右部分小的个数与该数的乘积 便可以得到答案
例如:
【1,2,4,1】
左边部分为1,2
右边部分为4,1
-process-:
归并排序应用:小数之和_排序算法
左边子合并合并产生一个1 右边子合并无
最终合并 对于1 产生一个 1 对于2 产生一个 2
结果为1+1+2=4
但和归并排序不一样的是,当左边和右边两个元素相等的时候,要先填充右边元素,因为需要计算比左边元素大的右边元素的个数。

Code

def merge_sort(lis,left,right):
# 数组为空
if left == right:
return 0

middle = left + (right - left) // 2

a = merge_sort(lis,left,middle)
b = merge_sort(lis,middle+1,right)
c = merge(lis,left,middle,right)

return a+b+c


def merge(lis,left,middle,right):
_lis = []
p = left
q = middle + 1
res = 0
while(p <= middle and q <= right):
if (lis[p] < lis[q]): # 注意条件
_lis.append(lis[p])
res += lis[p] * (right - q + 1) # 就是这里算值
p += 1
else:
_lis.append(lis[q])
q += 1

while(p<=middle):
_lis.append(lis[p])
p += 1

while(q<=right):
_lis.append(lis[q])
q += 1

lis[left:right+1] = _lis
return res
print(merge_sort([1,2,4,1],0,3))

换种写法,其实差别不大,只是为了延续
​​​归并排序​​ 仅此而已

def merge_sort(lis,left,right):
if left == right:
return 0
middle = left + (right - left) // 2

# 左边归并
a = merge_sort(lis,left,middle)
# 右边归并
b = merge_sort(lis,middle+1,right)

c = merge(lis,left,middle,right)

return a+b+c

def merge(lis,left,middle,right):
_lis = [0 for _ in lis]
i = 0 # 辅助数组位置指针
p = left # 左边数组位置指针
q = middle + 1 # 右边数组位置指针
res = 0
while(p<=middle and q <=right):
if lis[p] < lis[q]:
_lis[i] = lis[p]
res += lis[p] * (right - q + 1)
p += 1
else:
_lis[i] = lis[q]
q += 1
i += 1

while(p<=middle):
_lis[i] = lis[p]
i += 1
p += 1
while(q<=right):
_lis[i] = lis[q]
i += 1
q += 1

for i in range(right-left+1):
lis[left+i] = _lis[i] # 注意这里的lis[left+i]
return res
print(merge_sort([1,2,4,1],0,3))

今天给舅妈过生日,暂且这样,祝大家新年快乐。


精彩评论(0)

0 0 举报