【问题标题】:Implementing cartesian product, such that it can skip iterations实现笛卡尔积,使其可以跳过迭代
【发布时间】:2016-07-08 20:31:10
【问题描述】:

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

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

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

但是我可以实现它的唯一方法是首先对 2 个集合(“ab”,“ab”)进行笛卡尔乘积,然后从集合的输出中添加相同的集合。这是伪代码:

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

我想要的是直接开始计算最后一个集合,而不是计算它之前的所有集合。这是否可能,也是一个会给我类似结果的解决方案,但它不是笛卡尔积是可以接受的。 我阅读大多数通用编程语言都没有问题,所以如果你需要发布代码,你可以用任何你喜欢的语言来完成。

【问题讨论】:

  • 你已有的有什么问题?
  • 我想跳过迭代,因为上面的算法正在使用前一组,所以如果我想生成 {a,b} 8,首先 pc 必须计算 {a,b} x { a,b} 然后 ({a,b} x {a,b})x{a,b} ... 直到 8
  • 您实际上是在尝试解决问题(真正的瓶颈?)还是只是“为乐趣而优化”?
  • 解决问题是为了好玩吗?它将对我的其他项目有很大帮助,但这不是必需的。另外我不确定这个问题是否已经解决,我的意思是我不可能解决它
  • (有时)可以“为了好玩”寻找优化,但我总是想提醒人们read this first

标签: algorithm language-agnostic


【解决方案1】:

这是一个递归算法,它构建 S^n 而无需“首先”构建 S^(n-1)。想象一个无限的 k-ary 树,其中 |S| = k。用 S 的元素标记将任何父级连接到其 k 个子级的每条边。 S^m 的元素可以被认为是从根开始长度为 m 的任何路径。以这种思维方式,集合 S^m 是所有此类路径的集合。现在寻找 S^n 的问题是枚举所有长度为 n 的路径的问题——我们可以通过考虑从头到尾的边标签序列来命名路径。我们想直接生成 S^n 而不首先枚举所有 S^(n-1),因此修改深度优先搜索以查找深度 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 的解决方案中找到。

【讨论】:

  • 我在python中实现了这个,结果似乎是包含空列表的列表。更困扰我的是我不明白这是如何跳过迭代的。这是我的python代码:pastebin.com/i8TvPJEw
  • @DeyanGeorgiev 在伪代码中很清楚地看到,除非长度为 3,否则不能向成员添加任何内容。因此,如果它包含空列表,Python 正在做一些语义上没有被伪代码暗示的事情。我的钱是通过引用而不是值传递列表并分配引用而不是值。你能说出调试器中发生了什么吗?如果它是对象,则始终将当前的副本传递给 Products。
  • 我修复了代码,我需要复制“当前”,因为 current.pop 正在删除它的元素。但是我还是不懂算法
  • @DeyanGeorgiev 添加一些讨论。
猜你喜欢
  • 2017-09-28
  • 2011-01-26
  • 2012-08-27
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多