我需要打印出等于某个给定整数的列表元素的n个索引。确保该组合存在于列表中。例如,对于以下输入(数组中的元素数,所需乘数,所需子列表和给定数组中的元素数):
7 60 4
30 1 1 3 10 6 4
我应该以任何顺序得到
1 2 4 5
因为1 * 1 * 10 * 6 == 60。如果解决方案不止一种,我需要打印其中任何一种。
我的解决方案可以运行,但是速度很慢,如何使其运行更快?
from itertools import chain, combinations
arr = list(map(int, input().split()))
numbers = list(map(int, input().split()))
s = sorted(numbers)
def filtered_sublists(input_list, length):
return (
l for l in all_sublists(input_list)
if len(l) == length
)
def all_sublists(l):
return chain(*(combinations(l, i) for i in range(len(l) + 1)))
def multiply(arr):
result = 1
for x in arr:
result = result * x
return result
def get_indexes(data):
indexes = []
for i in range(len(data)):
if arr[1] == multiply(data[i]):
for el in data[i]:
if numbers.index(el) in indexes:
all_ind = [i for i, x in enumerate(numbers) if x == el]
for ind in all_ind:
if ind not in indexes:
indexes.append(ind)
break
else:
indexes.append(numbers.index(el))
break
return indexes
sublists = list(filtered_sublists(numbers, arr[2]))
print(*get_indexes(sublists))
答案 0 :(得分:0)
关键是不要测试每个组合。
def combo(l, n=4, target=60, current_indices=[], current_mul=1):
if current_mul > target and target > 0:
return
elif len(current_indices) == n and current_mul == target:
yield current_indices
return
for i, val in enumerate(l):
if (not current_indices) or (i > current_indices[-1] and val * current_mul <= target):
yield from combo(l, n, target, current_indices + [i], val * current_mul)
l = [30,1,1,3,10,6,4]
for indices in combo(l, n=4, target=60):
print(*indices)
打印:
1 2 4 5
更多测试用例:
l = [1,1,1,2,3,3,9]
for c, indices in combo(l, n=4, target=9):
print(*indices)
打印:
0 1 2 6
0 1 4 5
0 2 4 5
1 2 4 5
答案 1 :(得分:0)
我们可以为O(n * k * num_factors)
解决方案使用记忆式递归,其中num_factors
取决于我们可以创建目标产品的多少个因素。从代码中应该很清楚地发现重复发生。 (零没有被处理,但是添加额外的处理应该很简单。)
Python风格的JavaScript代码:
function f(A, prod, k, i=0, map={}){
if (i == A.length || k == 0)
return []
if (map[[prod, k]])
return map[[prod, k]]
if (prod == A[i] && k == 1)
return [i]
if (prod % A[i] == 0){
const factors = f(A, prod / A[i], k - 1, i + 1, map)
if (factors.length){
map[[prod, k]] = [i].concat(factors)
return map[[prod, k]]
}
}
return f(A, prod, k, i + 1, map)
}
var A = [30, 1, 1, 3, 10, 6, 4]
console.log(JSON.stringify(f(A, 60, 4)))
console.log(JSON.stringify(f(A, 60, 3)))
console.log(JSON.stringify(f(A, 60, 1)))
答案 2 :(得分:0)
您可以从目标产品开始,然后递归除以剩余列表中的因子,直到使用指定数量的因子降至1为止。这样做的好处是,可以快速消除递归的全部分支,而这些递归的数目不是目标乘积的一部分。
处理列表中的零值和目标乘积零时,在开始和遍历因子时需要几个特殊条件。
例如:
def findFactors(product, count, factors, offset=0):
if product == 0: return sorted((factors.index(0)+i)%len(factors) for i in range(count))
if not count: return [] if product == 1 else None
if not factors: return None
for i,factor in enumerate(factors,1):
if factor == 0 or product%factor != 0: continue
subProd = findFactors(product//factor,count-1,factors[i:],i+offset)
if subProd is not None: return [i+offset-1]+subProd
r = findFactors(60, 4, [30,1,1,3,10,6,4])
print(r) # [1, 2, 4, 5]
r = findFactors(60, 4, [30,1,1,0,3,10,6,4])
print(r) # [1, 2, 5, 6]
r = findFactors(0, 4, [30,1,1,3,10,6,0,4])
print(r) # [0, 1, 6, 7]