问题:我们是否可以选择所有三个数字并且时间复杂度为O(N^2)?
Illustration:
数组如下:
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。
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。
这可以在O(1)空间和O(N2)时间内完成。
首先让我们解决一个简单的问题:
给定两个数组 A
和 B
,从中选择一个元素,使它们的和等于给定的数字 K
。
对两个数组进行排序,这需要 O(NlogN) 的时间。
取指针 i
和 j
,其中 i
指向数组 A
的开头,j
指向数组 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
,则需要减小和,因此将 j
减一。在排序后查找配对的过程需要 O(N) 的时间。
现在让我们来看看原始问题。我们现在有了第三个数组,称其为 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
外层循环运行 N
次,每次运行我们执行一个 O(N) 的操作,使整个算法的时间复杂度为 O(N2)。
i
和j
向彼此靠近的部分:我记得这是正确的,但你需要解释一下原因,因为在这个过程中有一些元素对没有被检查到,比如,如果你在开始时将i
增加两次,然后将j
减少两次,则元素对(initial_i + 1, initial_j - 1)
永远不会被检查到。一个(充分但不必要的)方法是证明任何被跳过的元素对都不可能相加为K
。 - j_random_hackerA[i] + B[j] < K
,这意味着我们需要增加其中一个数字,但由于B
已经排序且j
是B
中的最后一个元素,即B
中的最大数字,因此唯一可能的方法是将i
增加以尝试下一个更大的数字。--如果A[i] + B[j] > K
,这意味着我们需要减少其中一个数字,但由于A
已经排序且i
是A
中的第一个元素,即从A
中可能得到的最小值,因此唯一可能的方法是将j
减少以尝试下一个更小的数字。--继续归纳。 - chakritA[i] + B[j] < K
,其中j 不是 B
的最后一个元素,我们就有了两个选项:要么像以前一样增加i
,要么增加j
。(对于A[i] + B[j] > K
的情况也是如此。) - j_random_hacker您可以将其简化为两个数组的相似问题,这是一个有点出名且具有简单的O(n)解决方案的问题(涉及从两端迭代)。
A
一次。B
和C
,使得B + C = M - A
。步骤2和3相乘给出了O(n^2)的复杂度。
1. 将所有的(i,j)对中A[i]*B[j]的结果存储在另一个数组D中,使用哈希数据结构进行组织。此步骤的复杂度为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
对最后一个列表进行哈希。在该特定列表上执行此操作的时间复杂度为O(N),但这将添加到下一阶段。
下一阶段是创建第一行和第二行总和的“矩阵”。然后在哈希表中查找它们匹配的数字是否存在。创建矩阵的时间复杂度为O(N*N),而在哈希表中查找的时间复杂度为常数级别。
对三个数组进行排序。然后初始化三个索引
k 指向 C 的第一个元素。 当 i、j、k 在各自的数组 A、B、C 的限制范围内时
如果 A[i]+B[j]+C[k] == M,则返回
如果 A[i]+B[j]+C[k] < M。如果 A[i]<=C[k] 则增加 i,否则增加 k。
应该在 O(n) 时间内运行。
我有另一种时间复杂度为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)
。
以O(N^2)的空间代价,但仍使用O(N^2)的时间,可以处理四个数组,通过计算前两个数组的所有可能和以及后两个数组的所有可能余数,对列表进行排序(由于它们都是'long'类型,其位数与N无关,因此可以在线性时间内完成),然后查看是否存在任何一组和等于任何一组余数。
对于所有3个数组,排序并使用二分查找似乎是更好的方法。一旦数组排序完成,应该绝对采用二分查找而不是线性查找,因为后者需要n而不是log(n)。
哈希表也是一个可行的选择。
哈希和排序的组合可以降低时间复杂度,但代价是O(N平方)的空间复杂度。