让[a_1 a_2 ... a_n]
成为[1,10n]
范围内不同整数的列表。如果有三个不同的元素true
,则提供返回x,y,z
的算法,否则-1 <= x+y-z <= 1
和false
。
强力算法(检查x+y-z
的所有可能组合,及时运行O(n^3)
。是否有更高效的算法?
答案 0 :(得分:1)
是的,有。以下是使用O(n^2)
额外空间的O(n)
最差情况算法。
想法是检查所有可能的对(而不是三元组),并迭代地标记您已经看到的元素,并将它们与每对的总和进行比较。
对于每一对,检查其总和是否具有匹配元素,该元素恰好是总和(x+y-z == 0
)或者如果添加1(x+y+1-z == 0 -> x+y-z = -1
)可以获得的元素,或者您可以访问你减少1(x+y-1-z == 0 -> x + y - z == 1
)
伪代码:
mark = new boolean[10n]; //all initialized to false
sort arr //O(nlogn)
for each i in n,1: (reverse order)
for each j in 1,i-1:
//neglected range check, make sure it is done
if (mark[arr[i]+arr[j]] || mark[arr[i]+arr[j]+1] || mark[arr[i]+arr[j]-1]):
return true
mark[arr[i]] = true
return false
请注意,我们将i
从n
迭代到1,因为z > x
和z > y
- 我们要确保我们检查所有已使用元素的对在列表中,如果它在那里
正确性证明:
如果有解x+y-z = 0
- 那么z > x
和z > y
(所有元素都是正不同的整数)。
不失一般性,我们假设x > y
。因此,在外部循环中迭代arr[i]=x
时,有j<i
个arr[j]=y
。此外,自z>x
- mark[z] == true
以来 - 因为我们在之前迭代它时标记了它。
因此:该算法将找到mark[arr[x] + arr[y]] == true
,并产生true
。
。+-1
个案的类似证明。
如果算法产生了真,那么它发现其中一个条件为真。我们假设它是mark[arr[i] + arr[j]]
(其他案例的证据将类似)。
所以,我们发现了mark[arr[i] + arr[j]] == true
- 所以我们插入了它,因为有一些元素z
使得z = arr[i] + arr[j]
,并且算法对于这种情况是正确的。