# Q：创建一个函数，检查数组是否有两个相反的元素，或者小于2。（C++）

Create a function that checks whether an array has two opposite elements or not for less than n^2 complexity. Let's work with numbers.

Obviously the easiest way would be:

``````bool opposite(int* arr, int n) // n - array length
{
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(arr[i] == - arr[j])
return true;
}
}

return false;
}
``````

I would like to ask if any of you guys can think of an algorithm that has a complexity less than n^2. My first idea was the following: 1) sort array ( algorithm with worst case complexity: n.log(n) ) 2) create two new arrays, filled with negative and positive numbers from the original array ( so far we've got -> n.log(n) + n + n = n.log(n)) 3) ... compare somehow the two new arrays to determine if they have opposite numbers

I'm not pretty sure my ideas are correct, but I'm opened to suggestions.

``````bool opposite(int* arr, int n) // n - array length
{
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(arr[i] == - arr[j])
return true;
}
}

return false;
}
``````

I would like to ask if any of you guys can think of an algorithm that has a complexity less than n^2. My first idea was the following: 1) sort array ( algorithm with worst case complexity: n.log(n) ) 2) create two new arrays, filled with negative and positive numbers from the original array ( so far we've got -> n.log(n) + n + n = n.log(n)) 3) ... compare somehow the two new arrays to determine if they have opposite numbers

An important alternative solution is as follows. Sort the array. Create two pointers, one initially pointing to the front (smallest), one initially pointing to the back (largest). If the sum of the two pointed-to elements is zero, you're done. If it is larger than zero, then decrement the back pointer. If it is smaller than zero, then increment the front pointer. Continue until the two pointers meet.

This solution is often the one people are looking for; often they'll explicitly rule out hash tables and trees by saying you only have O(1) extra space.

I would use an std::unordered_set and check to see if the opposite of the number already exist in the set. if not insert it into the set and check the next element.

``````std::vector<int> foo = {-10,12,13,14,10,-20,5,6,7,20,30,1,2,3,4,9,-30};
std::unordered_set<int> res;
for (auto e : foo)
{
if(res.count(-e) > 0)
std::cout << -e << " already exist\n";
else
res.insert(e);
}
``````

Output:

``````opposite of 10 alrready exist
``````

Live Example

``````std::vector<int> foo = {-10,12,13,14,10,-20,5,6,7,20,30,1,2,3,4,9,-30};
std::unordered_set<int> res;
for (auto e : foo)
{
if(res.count(-e) > 0)
std::cout << -e << " already exist\n";
else
res.insert(e);
}
``````

``````opposite of 10 alrready exist
``````

Let's see that you can simply add all of elements to the unordered_set and when you are adding x check if you are in this set -x. The complexity of this solution is O(n). (as @Hurkyl said, thanks)

UPDATE: Second idea is: Sort the elements and then for all of the elements check (using binary search algorithm) if the opposite element exists.

You can do this in O(n log n) with a Red Black tree.

``````t := empty tree
for each e in A[1..n]
if (-e) is in t:
return true
insert e into t
return false
``````

In C++, you wouldn't implement a Red Black tree for this purpose however. You'd use std::set, because it guarantees O(log n) search and insertion.

``````std::set<int> s;
for (auto e : A) {
if (s.count(-e) > 0) {
return true;
}
s.insert(e);
}
return false;
``````

As Hurkyl mentioned, you could do better by just using std::unordered_set, which is a hashtable. This gives you O(1) search and insertion in the average case, but O(n) for both operations in the worst case. The total complexity of the solution in the average case would be O(n).

``````t := empty tree
for each e in A[1..n]
if (-e) is in t:
return true
insert e into t
return false
``````

``````std::set<int> s;
for (auto e : A) {
if (s.count(-e) > 0) {
return true;
}
s.insert(e);
}
return false;
``````

c++  arrays  algorithm  complexity-theory