在等于m的列表中找到n个整数

时间:2019-08-24 14:13:33

标签: python python-3.x algorithm

我需要打印出等于某个给定整数的列表元素的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))

3 个答案:

答案 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]