我正在处理Google的一个FooBar挑战,以便在Google的运行时环境中执行时遇到时间限制超出错误。我的解决方案运行良好 - 在我的本地开发环境中很快就能实现。
这是我的代码:
from itertools import permutations
def answer(l):
options = []
for r in range(1, len(l) + 1):
for p in permutations(l, r=r):
n = int(''.join(map(str, p)))
if n % 3 == 0:
options.append(n)
numbers = sorted(options, reverse=True)
return numbers[0]
l = [3, 1, 4, 1, 5, 9]
#l = [3, 1, 4, 1]
print(answer(l))
目标是从传入的数字列表中找到可被3整除的最大数字。
两个例子的输出应该是:
[3, 1, 4, 1, 5, 9] => 94311
[3, 1, 4, 1] => 4311
根据注释从最大到最小(而不是从最小到最大)生成排列,然后突破,我修改了代码。反对,它适用于本地环境,但谷歌运行时表示超出了时间限制:
def answer(l):
options = []
l = sorted(l, reverse=True)
for r in range(len(l) + 1, 1, -1):
for p in permutations(l, r=r):
n = int(''.join(map(str, p)))
if n % 3 == 0:
return n
return 0
我正在根据permutations
docs对输入列表进行排序,如果输入已排序,则表示将对元组进行排序。然后,因为它应该排序,第一次找到一个可被3整除的值,这将是最高值
正如我所说,我的代码(两个版本)都有效。但是,我的运行时间似乎比谷歌预期的要长。如何减少上述代码的运行时间?
答案 0 :(得分:2)
最高的数字将包含最多的数字。所以对于 大小为n的列表,搜索应该从n开始并继续到n-1, N-2 ...
可被3整除的数字将始终位于解决方案中。对于 示例2514可以被3整除,因此是32514或35314.因此,您可以减少 搜索不能被3整除的数字。
对于不能被3整除的n位数字列表(n> = 3),您可以 通过删除最多 2位数,得到一个可被3整除的数字。这是因为求和将具有余数1或2.如果它是1,在最坏的情况下你可以删除2位数,余数为2.如果它是2,再次在最坏的情况下你可以删除2位数余数为1。
现在算法:
您有一个数字列表:
divisible = [i for i in numbers if i % 3 == 0]
candidate_list = [i for i in numbers if i % 3 != 0]
如果candidate_list的总和可以被3整除,那么你就得到了答案。如果没有,请查看其余部分:
remainder = sum(candidate_list) % 3
如果余数为1,我们将在候选列表中搜索1,4或7。如果它是2,则数字将是2,5和8.如果我们找到一个数字,我们将从列表中删除它,剩余数字的总和将被3整除。
if remainder!=0:
for i in range(3):
if (remainder + i*3) in candidate_list:
candidate_list.remove(remainder + i*3)
return candidate_list
这将从最小的数字开始搜索,并在找到数字时突破循环。如果没有,我们将搜索两位数而不是1.
counter = 0
for candidate in candidate_list:
if candidate % 3 + remainder == 3:
candidate_list.remove(candidate)
counter += 1
if counter > 1:
return candidate_list
总的来说,你会有这样的事情:
numbers = [3, 1, 4, 1, 5, 9, 0, 2, 4, 7, 9, 1, 3]
divisible = [i for i in numbers if i % 3 == 0]
def search(numbers):
candidate_list = sorted([i for i in numbers if i % 3 != 0])
remainder = sum(candidate_list) % 3
if remainder!=0:
for i in range(3):
if (remainder + i*3) in candidate_list:
candidate_list.remove(remainder + i*3)
return candidate_list
counter = 0
for candidate in candidate_list:
if candidate % 3 + remainder == 3:
candidate_list.remove(candidate)
counter += 1
if counter > 1:
return candidate_list
else:
return candidate_list
candidate_list = search(numbers)
fin = int(''.join(map(str, sorted(divisible + candidate_list, reverse=True))))