Time complexity:\(\mathcal{O}\left(n^3\right)\)
Because those three nested loops are required.
Auxiliary space:\(\mathcal{O}(1)\)
No extra space required.
Final verdict: not a valid solution due to our constraints.
Hashing Approach
Now it's time for a question: do we really need to check all the triplets?, of course not! (otherwise this interview question would be meaningless 😂). A second approach is due to if \(x + y + z = 0\) then \(x = -y - z\). So we just need to find a triplet where the first number is the opposite of the sum of second and third number. We could do this using almost eny kind of hashing data structure.
Below is the implementation in pseudocode of the above approach:
1
2
3
4
5
6
7
H<-hash_mapfori=0ton-1doforj=i+1ton-1doifH.contains(-A[i]-A[j])thenreturntrueH.insert(A[ i ])returnfalse
Time complexity:\(\mathcal{O}\left(n^2\right)\)
Because those two nested loops are required and time complexity for checking if a value exists in a hash map is \(\mathcal{O}(1)\).
Auxiliary space:\(\mathcal{O}(n)\)
Because at the end the hash map will contain \(n\) elements.
Final verdict: not a valid solution due to our constraints.
Two Pointers Approach
Another approach, and our final approach, is sorting the array \(A\) and then try to find a triplet \((i, j, k)\) such that \(0 \le i \lt j \lt k \lt n\) and \(A_i + A_j + A_k = 0\). Given any triplet \((i, j, k)\) such that \(0 \le i \lt j \lt k \lt n\) then there are just \(3\) options we need to check.
Following the above idea, we could iterate through every \(0 \le i \lt n\) and search for a valid pair of \((j, k)\) in the range \([i+1,n-1]\).
Demonstration
If there is no sulution, it's pretty obviuos that we don't find a solution, because we check the sum of \(3\) numbers and it will never be \(0\).
Let's assume there exists a triplet \((i, j, k)\) such that \(0 \le i \lt j \lt k \lt n\) and \(A_i + A_j + A_k = 0\). It is obviuos that our algorithm will reach \(i\) after some steps (maybe none). After that, it is also straightforward to see that we will reach either \(j\) or \(k\), because we iterate through every \(i \lt v \lt n\) and \(i \lt j,k\).
Suppose we reach \(j\) before \(k\), then with the right pointer we are at position \(k \lt p \lt n\) and \(\forall p: k \lt p \lt n \implies A_i + A_j + A_p \ge 0\) because \(A_i + A_j + A_k = 0\) and \(A_k \le A_p\) given that the array is sorted.
So either we found another valid solution with triplet \((i, j, p)\) or we have to decrease our right pointer until we reach \(k\) or another valid solution.
Suppose we reach \(k\) before \(j\), then with the left pointer we are at position \(i \lt p \lt j\) and \(\forall p: i \lt p \lt j \implies A_i + A_p + A_k \le 0\) because \(A_i + A_j + A_k = 0\) and \(A_p \le A_j\) given that the array is sorted.
So either we found another valid solution with triplet \((i, p, k)\) or we have to increase our left pointer until we reach \(j\) or another valid solution.
Solution
Here is the solution code of this problem in multiple languages.