实现笛卡尔积,使其可以跳过迭代

时间:2016-07-08 20:31:11

标签: algorithm language-agnostic

我想实现一个函数,它将返回set的笛卡尔积,重复给定的数字。例如

input: {a, b}, 2
output:
aa
ab
bb
ba

input: {a, b}, 3
aaa
aab
aba
baa
bab
bba
bbb

然而,我可以实现它的唯一方法是首先做2套(" ab"," ab)的cartesion产品,然后从套装的输出中添加相同的套装。这是伪代码:

function product(A, B):
    result = []
    for i in A:
        for j in B:
            result.append([i,j])
    return result
function product1(chars, count):
    result = product(chars, chars)
    for i in range(2, count):
        result = product(result, chars)
    return result

我想要的是直接开始计算最后一组,而不计算它之前的所有组。这是否可行,也是一种可以给我类似结果的解决方案,但它不是可接受的笛卡儿产品。 我没有阅读大多数通用编程语言的问题,因此如果您需要发布代码,您可以使用您熟悉的任何语言进行编写。

1 个答案:

答案 0 :(得分:1)

这是一个递归算法,它构建S ^ n而不构建S ^(n-1)“first”。想象一下无限的k-ary树,其中| S | = k。使用S的元素标记将任何父级连接到其k个子级的每个边。 S ^ m的元素可以被认为是从根开始的任何长度为m的路径。以这种思维方式,集合S ^ m是所有这些路径的集合。现在找到S ^ n的问题是枚举长度为n的所有路径的问题 - 我们可以通过从头到尾考虑边缘标签的顺序来命名路径。我们想要在没有首先枚举所有S ^(n-1)的情况下直接生成S ^ n,因此修改深度优先搜索以找到深度为n的所有节点似乎是合适的。这基本上是以下算法的工作原理:

// collection to hold generated output
members = []

// recursive function to explore product space
Products(set[1...n], length, current[1...m])

    // if the product we're working on is of the
    // desired length then record it and return
    if m = length then
        members.append(current)
        return

    // otherwise we add each possible value to the end
    // and generate all products of the desired length
    // with the new vector as a prefix
    for i = 1 to n do
        current.addLast(set[i])
        Products(set, length, current)
        currents.removeLast()

// reset the result collection and request the set be generated
members = []
Products([a, b], 3, [])

现在,广度优先方法的效率不亚于深度优先方法,如果你认为它与你正在做的事情没有什么不同。实际上,生成S ^ n的方法必须至少生成一次S ^(n-1),因为这可以在S ^ n的解中找到。