背景
出处:2018今日头条实习生笔试题4
原因是我的代码通过率只有30%提示时间超限,但是没时间去修改了,所以很不甘心,写出优化后的代码。
magic操作
给一个包含n个元素的集合a和包含m个元素的集合b,定义一magic种操作,从一个集合中取出一个元素放入另一个集合中,使得两个集合的平均值都变大了。问一共可以进行多少次magic操作。
分析
要达到magic操作,那么取出的这个元素,必须是小于要取出集合的平均值(这样取出后集合的平均值才会变大),而且必须大于要放进的集合的平均值(这样放进一个元素后集合的平均值才会变大),而且该元素不能是属于要放进元素的集合(因为集合的特殊型,不能有重复元素,放入重复元素,集合的平均值不该变)。
代码
# coding=utf-8
import sys
(m,n) = sys.stdin.readline().split()
m = int(m)
n = int(n)
lm = [int(i) for i in sys.stdin.readline().split()]
ln = [int(i) for i in sys.stdin.readline().split()]
#求平均值
aver_m = sum(lm) / m
aver_n = sum(ln) / n
#排序
lm.sort()
ln.sort()
#定义magic操作的次数
times = 0
while True:
#记录要操作的元素
data = None
#记录取元素和追加元素的列表
item_remove = lm
item_append = ln
for i in lm:
#因为已经排序了,所以遇到大于平均值的就不用去找了
if i >= aver_m:
break
else:
if i > aver_n and i not in ln:
data = i
break
if not data:
#在第一个列表里找不到就去第二个找
for i in ln:
if i >= aver_n:
break
else:
if i > aver_m and i not in lm:
item_append = lm
item_remove = ln
data = i
break
if not data:
break
else:
times += 1
item_remove.remove(data)
item_append.append(data)
#优化了求平均值
if item_remove is lm:
m -= 1
n += 1
aver_m = (aver_m * (m + 1) - data) / m
aver_n = (aver_n * (n - 1) + data) / n
else:
m += 1
n -= 1
aver_m = (aver_m * (m - 1) + data) / m
aver_n = (aver_n * (n + 1) - data) / n
print(times)
优化
已有的优化
- 不使用set,只用list即可。因为题目告诉输入的就是不重复的元素,并且不会出现给列表里放同样值的情况
- 只对列表排一次序,从小到大找,找到大于平均值的就不去找了
- 优化了求平均值的算法,不是sum(a)/len(a)
还可以继续优化的地方
- 可以用下标去记录上次查找到的位置,因为如果n不满足
平均值1<n<平均值2
,当平均值都增大了n还是不满足。 - 如果第一个列表里已经没有合适的值了那么以后也不会再有合适的值了。