【问题标题】:Finding set of products formed by two lists查找由两个列表组成的产品集
【发布时间】:2020-02-20 01:34:00
【问题描述】:

给定两个列表,假设 A = [1, 3, 2, 7] 和 B = [2, 3, 6, 3]

找出可以通过将 A 中的数字与 B 中的数字相乘来形成的所有产品的集合。(通过集合,我的意思是我不想要重复)。我正在寻找最快的运行时间。 不允许使用哈希函数

第一种方法是蛮力,我们将 A 中的每个数字与 B 中的每个数字相乘,如果我们找到一个不在列表中的产品,则将其添加到列表中。查找所有可能的产品将花费O(n^2),并且要验证该产品是否已经存在于列表中,我将花费O(n^2)。所以总数达到O(n^4)

我正在寻求优化此解决方案。我想到的第一件事是删除列表 B 中的重复项。在我的示例中,我有 3 个作为重复项。我不需要再次计算 A 中所有元素与重复 3 的乘积。但这仍然无助于减少整体运行时间。

我猜如果 A 和 B 中的所有数字组合起来都是唯一的 AND 素数,那么最快的运行时间可能是 O(n^2)。这样可以保证不会有重复,我不需要验证我的产品是否已经出现在列表中。所以我在想我们是否可以预处理我们的输入列表,以保证产品价值的唯一性(预处理的一种方法是像我上面提到的那样删除列表 B 中的重复项)。

这在O(n^2) 时间是否可行?如果我只关心可能的唯一产品的数量而不是实际产品的数量,这会有所不同吗?

for i = 1 to A.length:
    for j = 1 to B.length:
        if (A[i] * B[j]) not already present in list: \\ takes O(n^2) time to verify this
            Add (A[i] * B[j]) to list
        end if
    end for
end for

print list

上述输入的预期结果:2、3、6、9、18、4、12、14、21、42

编辑:

我可以想到一个O(n^2 log n) 的解决方案:

1) 我生成所有可能的产品值而不用担心重复\这是O(n^2)

2) 对这些产品值进行排序\这将是O(n^2 log n),因为我们有 n^2 个数字要排序

3) 由于元素现在已排序,因此在线性时间内删除重复项

【问题讨论】:

  • "如果 A 和 B 中的所有数字组合都是唯一的。这样可以保证不会有重复",这是不正确的,A 和 B 中的所有数字都必须是唯一的 AND 素数
  • @FrançoisHuppé Omg 是的,你是对的。如果 A = [4, 6, 10] - B = [8, 20] 那么 (4, 20) 和 (10, 8) 是 80。我将编辑我的帖子。感谢您指出这一点。
  • 您可以使用二叉搜索树/b-trees(一些语言,如 Rust 已经在标准库中具有基于 b-tree 的集合结构)将查找时间缩短到 log n 以使您的整体算法n^2 log n.
  • @EvilTak 如果我想要整体n^2 log n我也可以想一个更简单的方法而不使用tress?我最后用那个解决方案编辑了我的帖子。这有意义吗?
  • 那么我认为你已经有了最好的时间复杂度,除非你会使用像基数排序这样的东西(猜测位数是恒定的,因为你处理的是 int 或 long),所以时间复杂度排序是 O(n^2),整体时间复杂度也是 O(n^2),这显然是你能达到的最好的。

标签: algorithm list performance runtime


【解决方案1】:

使用集合消除重复。

    A=[3, 6, 6, 8]
    B=[7, 8, 56, 3, 2, 8]
    setA = set(A)
    setB = set(B)
    prod=set()  #empty set

    [prod.add(i*j) for i in setA for j in setB]
    print(prod)
    {64, 448, 6, 168, 9, 42, 12, 16, 48, 18, 336, 21, 24, 56}

复杂度为 O(n^2)。

另一种方法如下。 O(n^3) 复杂度

 prod=[]
    A=[1,2,2,3]
    B=[5,6,6,7]

    for i in A:
              for j in B:
                  if prod==[]:
                      prod.append(i*j)
                      continue
                  for k in range(len(prod)):
                    if i*j < prod[k]:
                     prod.insert(k,i*j)
                     break
                    elif i*j == prod[k]:
                     break
                    if k==len(prod)-1:
                     prod.append(i*j)
    print(prod)

另一种方式。这可能是在内部使用哈希函数。

   from toolz import unique
    A=[1,2,2,3]
    B=[5,5,7,8]
    print(list(unique([i*j for i in A for j in B])))

【讨论】:

  • 我认为Set是一个接口?您需要为您的解决方案实现类似 HashSet 的东西,在我的算法中,不允许使用哈希函数!
  • 我在哪里使用过哈希函数? Set 是一种抽象的数据结构。界面如何?
  • 在 Java 中,Set 是一个接口。我查看了 Python 中的 Set 在内部是如何工作的,它使用了哈希表。
  • 添加到上一个答案
猜你喜欢
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 2021-12-14
  • 2022-01-25
相关资源
最近更新 更多