I want to understand how @Stef's O(n ^ 2) is actually O(n ^ 2). Build vector constructs table[l] = {.....} and it takes 2 points. In the worst case, there might be only one l and all of (n ^ 2) points will fall into that bucket. Now, for (a, b), (c, d) in combinations(l, 2), this contains (n ^ 2) = M elements. He enumerates all the 2-point possibilities => O(M * M) = O(n ^ 4).