面试问题:三个阵列和O(N * N)

时间:2010-10-21 12:12:09

标签: arrays algorithm

假设我们有三个长度为 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 从第三个开始。

11 个答案:

答案 0 :(得分:151)

这可以在O(1)空间和O(N 2 )时间内完成。

首先让我们解决一个更简单的问题:
给定两个数组AB从每个数组中选择一个元素,使它们的总和等于给定的数字K

对需要O(NlogN)的数组进行排序。
选择ij指针,使i指向数组A的开头,j指向{{1}的结尾}}。
找到总和B并将其与A[i] + B[j]

进行比较
  • 如果K我们找到了 对A[i] + B[j] == KA[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)解决方案(涉及从两端迭代)。

  1. 对所有数组进行排序。
  2. 尝试从第一个数组中的每个数字A
  3. 查看最后两个数组是否可以为我们提供数字BC,以便B + C = M - A
  4. 步骤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 + BW = Ai + CAi是当前元素)。 Ai + B表示此新数组V的每个元素都是BAiA中的当前元素)中该位置的元素。 W = Ai + C类似。

现在,合并VW,就像合并排序一样。由于两者都已排序,因此为O(N)。在这个包含2*N元素的新数组中,搜索M + Ai(因为Ai使用了两次)。这可以在O(log n)中使用二进制搜索来完成。

因此,总复杂度为O(N^2)

答案 9 :(得分:1)

对三个数组进行排序。然后初始化三个索引

  1. 我指着A的第一个元素,
  2. j指向B的最后一个元素
  3. k指向C的第一个元素 虽然i,j,k在它们各自的阵列A,B,C

  4. 的范围内
  5. 如果A [i] + B [j] + C [k] == M返回

  6. 如果A [i] + B [j] + C [k]&lt; M.如果A [i]&lt; = C [k]否则增加k,则增加i。

  7. 如果A [i] + B [j] + C [k]> M. Decrement j。
  8. 哪个应该在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是否存在于散列中。