首先。在最坏的情况下找到所有三元组是O(n^3)
. 假设你有n=3k
数字。其中 K 为 3,k 为 4,k 为 5。
3,....,3,4,....,4,5,.....5
有k^3 = n^3/27 = O(n^3)
这样的三胞胎。只是打印它们需要O(n^3)
时间。
接下来将以这种形式解释 3SUM 问题:
它们每个都有数字s_1, ..., s_n
range [-u;u]
。a,b,c
那有多少个三胞胎a+b=c
?
转变。获取 2*u 个数字a_-u, ..., a_0, a_1, ... a_u
。a_i
是数字的数量s_j
,那s_j = i
。这是在O(n+u)
res = a_0 * sum(i=-u..u, i=/=0, C(a_i, 2)) + C(a_0,3)
a_0 = 0
建立一个多项式P(x) = sum(i = -u...u, a_i*x^(i+u)
。
Q(x) = P(x)*P(x)
使用FFT查找。
请注意Q(x) = sum(i=-2u..2u, b_i*x^(i+2*u))
,其中b_i
是对数s_u
,s_k
即s_u+s_k = i
(这包括两次使用相同的数字)。
对于所有甚至i
做b_i = b_i - a_(i/2)
。这将使用相同的号码删除两次。
- 总和
b_i*a_i/2
- 将其添加到 res 中。
示例:为了更简单,我将假设数字的范围是 [0..u],并且不会使用任何 x 次方的 +u。假设我们有数字1,2,3
-a_0 = 0, a_1 = 1, a_2 = 1, a_3 = 1
res = 0
P(x) = x + x^2 + x^3
Q(x) = x^2 +2x^3+3x^4+2x^5+x^6
减去后b_2 = 0, b_3 = 2, b_4 = 2, b_5 = 2, b_6 = 0
res += 0*1/2 + 2*1/2 + 2*0/2 + 2*0/2 + 6*0/2 = 1