Python 已超出Itertools.COMPLORIES()提升时间限制
我试图解决这个Python编码问题: 描述:安布罗西奥老师正在教他的学生二进制数 女儿安布罗西尼塔,所以他决定创造一个游戏 安布罗西奥将给安布罗西尼塔N个数字,后者可以选择K个数字 在最初的N中,每选一个数字,她就得一分 相当于使用二进制表示的1的数目 号码 帮助安布罗西尼塔了解她能获得多少积分 条目: 第一个输入行包含一个整数T,表示数字 测试用例的数量 每个测试用例从一行开始,该行包含整数N(总数) 和K(可选择的数字) 每个案例的最后一个输入行包含N个整数,表示 安布罗西尼塔可以选择的数字 输出: 对于每个测试用例,打印一行,其中包含Ambrosinita的多少个点 我能挣 一,≤ T≤ 十, 一,≤ N≤ 10^3 0≤ K≤ N 0≤ 数字≤10^5 执行时间限制为2秒。我得到一个TLE错误,但输出与预期的相同。因此,输入必须具有一定的长度 这是我的密码:Python 已超出Itertools.COMPLORIES()提升时间限制,python,python-3.x,performance,Python,Python 3.x,Performance,我试图解决这个Python编码问题: 描述:安布罗西奥老师正在教他的学生二进制数 女儿安布罗西尼塔,所以他决定创造一个游戏 安布罗西奥将给安布罗西尼塔N个数字,后者可以选择K个数字 在最初的N中,每选一个数字,她就得一分 相当于使用二进制表示的1的数目 号码 帮助安布罗西尼塔了解她能获得多少积分 条目: 第一个输入行包含一个整数T,表示数字 测试用例的数量 每个测试用例从一行开始,该行包含整数N(总数) 和K(可选择的数字) 每个案例的最后一个输入行包含N个整数,表示 安布罗西尼塔可以选择的数字
import itertools
test_cases = int(input())
def binary(num):
return format(num,'b')
def filter_string_1s(string):
aux = ''
for i in string:
if i == '1':
aux += i
return aux
for i in range(test_cases):
k = input().split()
k = int(k[1])
values = input().split()
values = [int(i) for i in values]
values = [filter_string_1s(str(binary(i))) for i in values]
bin_values = []
for combination in itertools.combinations(values,k):
aux = 0
for bin_number in combination:
for i in bin_number:
if i == '1':
aux += 1
bin_values.append(aux)
print(max(bin_values))
问题:为了在执行期限内解决问题,我应该采取哪些步骤来优化它
TLE=超过时间限制这是一个“top-k”问题,而不是需要“k”组合的问题。为了便于阅读,让我们选择N=990,K=7。你需要在990分的列表中选择前7名
通过生成C(990,7)=912459983564271542400个组合,然后确定每个组合中的7个数字中的每一个都有多少位1
。这就是为什么你没有时间了:你有990个数字要考虑,但是你在输入中重复每一个数字的比特数倍。
别说了。你所需要的只是浏览一下这个列表,并保留前7位的计数。列表中的7个数字之间没有交互作用。事实上,你甚至不必报告数字,只需报告总分
从七个零开始。现在遍历所有990个数字。任何时候你发现一个大于列表中最小元素的位计数(保持排序以便于参考),然后用新的分数替换它(并重新排序)。在所有990个数字的末尾,sum
列表
此外,计算比特数比你现在做的要容易得多。将
int
转换为二进制字符串,并使用str.count(1)
查看其中有多少1
位。她可以通过选择具有最多1位的K个数字来获得最大点数。因此,您只需计算每个数字的点,然后取顶部的K
例如:
import random
def maxPoints(K,N=None,numbers=None):
numbers = numbers or [random.randrange(0,100001) for _ in range(N)]
points = sorted(bin(n).count("1") for n in numbers)
return sum(points[-K:])
mp = maxPoints(3,numbers=[1,2,3,4,5])
print(mp) # 5
mp = maxPoints(1000,1000)
print(mp) # will return instantly
解决了!谢谢大家 代码:
请把问题编辑成你的问题。我无法通过链接查看它。欢迎使用堆栈溢出!请提供您试图解决的问题的简要说明,而不是指向外部站点的链接。您知道为什么需要2秒以上的时间吗?你认为循环
itertools.combinations(value,k)
可以进行多少次迭代?@KevinWang在使用itertools.combinations()之前,我曾尝试从列表中删除重复的元素,但没有成功(我仍然得到了TLE)。@flsantos0101但是会有多少次迭代?值的大小可以有多大?首先,对于范围(k):
,sum+=nums[-1]
,delnums[-1]
是拼写mysum=sum(nums[-k:])的缓慢方式(注意,变量名更改;sum
是一个内置变量,因此,如果命名局部变量sum
,则不能使用它)第二,如果允许导入,并且nums
的总大小足够大,那么使用import
ingheapq
并使用heapq.nlargest
(只返回k
最大元素的list
)替换sort
和切片可能会有一点好处(n log k)
而不是排序O(n log n)
work)。有见地的评论!上面的代码执行时间为0.0448s。按照建议编辑后,它略微降低到0.0479s。谢谢!注意:第4段中描述的算法基本上就是heapq.nlargest
为您所做的(它不保持它的排序,它只是保持它是一个堆,排序是最后一步;保持堆不变比保持完全排序的状态稍微便宜一些)。
test_cases = int(input())
for i in range(test_cases):
k = input().split()
k = int(k[1])
nums = input().split()
nums = [format(int(i),'b').count('1') for i in nums]
nums.sort()
sum = 0
for i in range(k):
sum += nums[-1]
del nums[-1]
print(sum)