我的目标是创建一个将列表作为输入的函数,并以sum(list)
为最小值的方式更改该列表。
该函数还接收一个int k
;该函数将执行k
次ceil(num(i)/2)
次,其中i
应该是max(list)
以获得最小和。
我正在尝试提高大型列表的搜索结果速度,但是我不能使用numpy
。所以对于7,20,10和k = 4结果列表= 14
def minmin(list, k):
for i in range(k):
maxind = list.index(max(list))
maxnum = math.ceil(list[maxind] / 2)
list[maxind] = maxnum
return sum(list)
答案 0 :(得分:0)
鉴于您的解释和限制,没有什么可以改善的;您已经在使用list.index()
和max()
,并利用了内置C实现的所有优势。
唯一不同的是临时变量的分配和对math.ceil()
的调用;阅读here,以了解ceil()
的替代方法。
另一种可能性是按降序对列表进行排序,以便搜索能更快地找到元素。
这里是一个稍微改进的版本; f1
是您的版本,另一个是我的建议。
def f1(input_list, repetitions):
input_list = list(input_list)
for _ in range(repetitions):
idx = input_list.index(max(input_list))
new_num = math.ceil(input_list[idx] / 2)
input_list[idx] = new_num
return sum(input_list)
def f2(input_list, repetitions):
input_list = list(input_list)
input_list.sort(reverse=True)
for _ in range(repetitions):
idx = input_list.index(max(input_list))
input_list[idx] = ((input_list[idx] + 1) // 2)
return sum(input_list)
用于比较持续时间并确保结果相同的代码:
import random
import timeit
for exp_n in range(2, 5):
n = 10**exp_n
numbers = [random.randint(1, 9999) for _ in range(n)]
for exp_k in range(2, 5):
k = 10**exp_k
t1 = timeit.timeit(
'f(numbers, k)', 'from __main__ import numbers, k, f1 as f',
number=10)
t2 = timeit.timeit(
'f(numbers, k)', 'from __main__ import numbers, k, f2 as f',
number=10)
print('n {:10,d} | k {:10,d} | {:10.4f} | {:10.4f} | best f{}'.format(
n, k, t1, t2, '1' if t1 < t2 else '2'))
assert f1(numbers, k) == f2(numbers, k)
结果是(在Python 3.6
上使用Ubuntu
):
n 100 | k 100 | 0.0027 | 0.0025 | best f2
n 100 | k 1,000 | 0.0280 | 0.0251 | best f2
n 100 | k 10,000 | 0.2097 | 0.1872 | best f2
n 1,000 | k 100 | 0.0232 | 0.0190 | best f2
n 1,000 | k 1,000 | 0.2295 | 0.2009 | best f2
n 1,000 | k 10,000 | 2.2607 | 2.1653 | best f2
n 10,000 | k 100 | 0.2139 | 0.1903 | best f2
n 10,000 | k 1,000 | 2.1379 | 1.6530 | best f2
n 10,000 | k 10,000 | 21.3588 | 18.8767 | best f2
如您所见,反向排序确实有帮助。