假设我们有三个长度为 N 的数组,其中包含任意数量的long
类型。然后我们会给出一个数字 M (相同类型),我们的任务是选择三个数字 A , B 和 C 每个数组一个(换言之 A 应从第一个数组中挑选 B 从第二个数据 C < / strong>来自第三个)所以总和 A + B + C = M 。
问题:我们可以选择所有三个数字并最终得到 O(N 2 )的时间复杂度吗?
插图:
阵列是:
1) 6 5 8 3 9 2
2) 1 9 0 4 6 4
3) 7 8 1 5 4 3
M 我们已经获得 19 。 然后我们选择 8 从第一个开始, 4 从第二个开始, 7 从第三个开始。
答案 0 :(得分:151)
这可以在O(1)空间和O(N 2 )时间内完成。
首先让我们解决一个更简单的问题:
给定两个数组A
和B
从每个数组中选择一个元素,使它们的总和等于给定的数字K
。
对需要O(NlogN)的数组进行排序。
选择i
和j
指针,使i
指向数组A
的开头,j
指向{{1}的结尾}}。
找到总和B
并将其与A[i] + B[j]
K
我们找到了
对A[i] + B[j] == K
和A[i]
B[j]
,我们需要
增加总和,所以增加A[i] + B[j] < K
。i
,我们需要
减少总和,因此递减A[i] + B[j] > K
。排序后找到对的过程需要O(N)。
现在让我们解决原始问题。我们现在有第三个数组称为j
。
所以算法现在是:
C
外部循环运行foreach element x in C
find a pair A[i], B[j] from A and B such that A[i] + B[j] = K - x
end for
次,对于每次运行,我们执行O(N)运算,使整个算法成为O(N 2 )。
答案 1 :(得分:13)
你可以将它减少到两个数组的类似问题,这有点着名并且有简单的O(n)解决方案(涉及从两端迭代)。
A
。B
和C
,以便B + C = M - A
。步骤2和3乘以给出O(n ^ 2)复杂度。
答案 2 :(得分:9)
其他解决方案已经更好了,但无论如何这里是我的O(n ^ 2)时间和O(n)内存解决方案。
将数组C的所有元素插入哈希表。 (时间复杂度O(n),空间O(n)) 取所有对(a,b),a来自A和b来自B(时间复杂度O(n ^ 2))。 对于每对,检查hastable中是否存在M-(a + b)(每个查询预期的复杂度O(1))。
因此,总体时间复杂度为O(n ^ 2),哈希表的空间复杂度为O(n)。
答案 3 :(得分:3)
哈希最后一个列表。执行此操作所花费的时间是该特定列表上的O(N),但这将添加到下一阶段。
下一阶段是创建前两行总和的“矩阵”。然后在哈希中查找匹配的数字是否存在。创建矩阵是O(N * N),而在哈希中查找是恒定时间。
答案 4 :(得分:3)
我有一个解决方案。将列表中的一个元素插入哈希表中。这不会花费O(n)时间。
一旦完成,你会找到剩下的2个数组中的所有对,看看它们的总和是否存在于哈希表中。
因为哈希连接是常数,所以我们总共获得了二次时间。
使用此方法可节省排序时间。
另一个想法是,如果你知道每个元素的最大大小,你可以使用存储桶排序的变体,并在nlogn时间内完成。
答案 5 :(得分:3)
1.以散列数据结构组织的另一个阵列D中的所有对(i,j)存储A [i] * B [j]。这一步的复杂性是O(N * N)。
construct a hash named D
for i = 1 to n
for j = 1 to n
insert A[i]*B[j] into D
2.对于阵列C中的每个C [i],找出D中是否存在M-C [i]。该步骤的复杂度是O(N)。
for i = 1 to n
check if M - C[i] is in D
答案 6 :(得分:1)
以O(N ^ 2)空间为代价,但仍然使用O(N ^ 2)时间,通过计算前两个数组的所有可能总和,可以处理四个数组,以及最后两个中所有可能的残差,对列表进行排序(可能是线性时间,因为它们都是'long'类型,其位数与N无关),然后查看是否有任何和等于任何残差。
答案 7 :(得分:1)
对所有3个阵列进行排序并使用二进制搜索似乎是一种更好的方法。一旦对数组进行了排序,就应该选择二进制搜索而不是线性搜索,它采用n而不是log(n)。
哈希表也是一个可行的选择。
散列和排序的组合可以降低时间,但是以O(N平方)空间为代价。
答案 8 :(得分:1)
我有另外O(N^2)
时间复杂度,O(N)
额外的空间复杂度解决方案。
首先,对三个数组进行排序,此步骤为O(N*log(N))
。然后,对于A
中的每个元素,创建两个数组V = Ai + B
和W = Ai + C
(Ai
是当前元素)。 Ai + B
表示此新数组V
的每个元素都是B
加Ai
(A
中的当前元素)中该位置的元素。 W = Ai + C
类似。
现在,合并V
和W
,就像合并排序一样。由于两者都已排序,因此为O(N)
。在这个包含2*N
元素的新数组中,搜索M + Ai
(因为Ai
使用了两次)。这可以在O(log n)
中使用二进制搜索来完成。
因此,总复杂度为O(N^2)
。
答案 9 :(得分:1)
对三个数组进行排序。然后初始化三个索引
k指向C的第一个元素 虽然i,j,k在它们各自的阵列A,B,C
如果A [i] + B [j] + C [k] == M返回
如果A [i] + B [j] + C [k]&lt; M.如果A [i]&lt; = C [k]否则增加k,则增加i。
哪个应该在O(n)中运行。
答案 10 :(得分:0)
怎么样:
for a in A
for b in B
hash a*b
for c in C
if K-c is in hash
print a b c
这个想法是在A和B中散列所有可能的对。接下来对于C中的每个元素,看看残差zum是否存在于散列中。