查找两个数组元素的最大有效组合数

时间:2013-07-08 12:46:05

标签: python algorithm python-3.x

有两个n长度数组(ab)由整数组成> 2。

在每个回合中,我想从每个数组(a[i]b[j])中删除一个整数,因为它们的某个条件为真(例如它们不是共同素数)。 (如果条件不成立,我会尝试删除另一个组合)

毕竟我想找到我能达到的最大转数(直到没有可能的组合去除哪个符合条件)。我们称之为最佳转弯次数。

我尝试使用搜索算法和使用Python的PriorityQueue解决此问题:

def search(n, a, b):
    q = queue.PriorityQueue()
    encountered = set()
    encountered.add((tuple(a), tuple(b)))
    q.put((number_of_coprime_combinations(a, b), a, b))

    while q:
        cost, a, b = q.get()
        combs = not_coprime_combinations(a, b)

        if not combs:
            return n - len(a)

        for a, b in combs:
            if not (tuple(a), tuple(b)) in encountered:
                q.put((number_of_coprime_combinations(a, b), a, b))
                encountered.add((tuple(a), tuple(b)))

number_of_coprime_combinations(a, b)返回给定数组ab的可能的联合素数组合的数量。这用作两个数组的给定状态的成本。

def number_of_coprime_combinations(a, b):
    n = 0

    for idx_a, x in enumerate(a):
        for idx_b, y in enumerate(b):
            if is_coprime(x, y):
                n += 1

    return n

not_coprime_combinations(a, b)会返回可能的状态列表,其中已从ab移除了非联合素数组合:

def not_coprime_combinations(a, b):
    l = []

    for idx_a, x in enumerate(a):
        for idx_b, y in enumerate(b):
            if not is_coprime(x, y):
                u, v = a[:], b[:]
                del(u[idx_a])
                del(v[idx_b])
                l.append((u, v))

    return l

>>> not_coprime_combinations([2,3],[5,6])
[([3], [5]), ([2], [5])]

问题在于这种解决方案对于大型整数数组而言效率非常低。所以我想知道这个问题是否有更好的解决方案..

示例:

n = 4
a = [2, 5, 6, 7] 
b = [4, 9, 10, 12]

可以删除:

(2, 4)
(5, 10)
(6, 9)

这将导致最佳解决方案:

a = [7]
b = [12]

但如果有人会删除:

(6, 12)
(2, 10)

人们会得到次优的解决方案:

a = [5, 7]
b = [4, 9]

算法应始终达到最佳匝数(在本例中为3)。

3 个答案:

答案 0 :(得分:3)

据我所知,要解决这个问题:

  • 构造二分图G,使得对于每个Ai和Bj,如果GCD(Ai,Bj)>如图1所示,G中存在边缘(Ai,Bj)。

  • 找到G

  • 最大匹配
  • 匹配的基数是解决方案

我不知道如何更快地解决这个问题。

答案 1 :(得分:1)

我知道你遇到了这个问题。 而你解决这个问题是错误的,因为它的O(n ^ 2)和贪婪。 n <= 10 ^ 5。 2&gt; a,b&lt;数组10 ^ 9

我认为在这个问题上你必须找到一些技巧。并且所有用于二分图中最大匹配的算法都是TL。

答案 2 :(得分:0)

假设:

  1. 定义了函数is_coprime_pair(pair),接受长度为2的列表并返回True 对于一对素数
  2. ab是可以组合的迭代
  3.     import itertools  
        not_coprimes = itertools.filterfalse(is_coprime_pair, itertools.product(a, b))
    

    not_coprimes将保留所有不包含两个素数的对