找到与给定数字相乘的数字的有效方法
Posted
技术标签:
【中文标题】找到与给定数字相乘的数字的有效方法【英文标题】:Efficient way to find numbers that multiply to given numbers 【发布时间】:2020-05-24 07:34:42 【问题描述】:我得到了2
列表、a
和 b
。它们都只包含整数。 min(a) > 0
、max(a)
最高可达1e10
和max(abs(b))
最高可达1e5
。我需要找到元组的数量(x, y, z)
,其中x
在a
中,y, z
在b
中,这样x = -yz
。 a
和 b
中的元素个数最多可达1e5
。
我的尝试:
我想出了一个幼稚的n^2
算法。但是,由于大小可以达到 1e5,我需要提出一个nlogn
解决方案(最大)。我所做的是:
将b
拆分为bp
和bn
,其中第一个包含所有正数,第二个包含所有负数并创建它们的映射。
然后:
2.1 我遍历 a
以获取 x
的。
2.2 遍历bn
和bp
中较短的一个。检查当前元素是否除以x
。如果是,请使用map.find()
查看z = -x/y
是否存在。
什么是有效的方法?
【问题讨论】:
也许您可以分解x
以获得它的所有质因数。如果只有一个,那么只有y = a, z = 1
是一个解决方案。如果有两个或更多,您将不得不搜索所有因子对 x0, x1
其中 x0*x1 = x
并找到您在步骤 2 中已经完成的那些。至少这样,您不只是暴力破解所有值的a
(其中可以有很多)。
可以,但远低于10000000000
。
您可以为a
、map[a[i]] = true
创建map
hash-container,据我所知b
可以是正数和负数,因此您可以通过快速排序对数组进行排序。因此,您可以找到“中性”元素 - 负数或零之后的第一个正数。在您可以对多个数字使用嵌套for循环后(外部循环只有负数,内部只有正数),乘法的结果用于检查映射map[b1*b2] == true
中是否有这个结果@
@AyratArifullin 这与我所做的非常相似。复杂性仍然存在O(n^2)
@AyratArifullin b
可以有1e5
元素,它们可以和1e5
一样大。这些数字不能相乘,会导致溢出
【参考方案1】:
第 1 步:对列表 b
中的元素进行排序(比如 bsorted
)
第 2 步:对于 a
中的值 x
,遍历列表 bsorted
中 bsorted
中的每个值 y,并在 bsorted
上对 (-x/y) 进行二进制搜索以找到 z
复杂度 |a|=m 和 |b|=n 复杂度为 O(mnlogn)
【讨论】:
【参考方案2】:没有 O(n*logn) 因为:z = -x/y
log(z) = log(-x) - log(y)
正如https://***.com/users/12299000/kaya3 所提到的,它是3SUM#3_different_arrays。根据***:
Kane、Lovett 和 Moran 表明 3SUM 的 6 线性决策树复杂度为 O(n*log^2n)
【讨论】:
【参考方案3】:这是一个未经验证的想法。从b
的元素创建trie,其中“字符”是有序的素数。对于a
中的每个元素,遍历trie 中的所有有效路径(DFS 或 BFS,其中测试能够被当前节点进一步划分),并且对于到达的每个叶子,检查剩余元素(在划分后每个节点)都存在于b
中。 (我们可能需要通过存储每个“单词”的计数并使用简单的组合来处理重复项。)
【讨论】:
以上是关于找到与给定数字相乘的数字的有效方法的主要内容,如果未能解决你的问题,请参考以下文章