See the original problem on HackerRank.
Given an array of integers A
sorted in nondecreasing order, return an array of the squares of each number, also in sorted nondecreasing order, in linear time.
Input Format
The first line contains N
, the length of the array.
The second line contains N
spaceseparated integers, the elements of the array.
Constraints
 \(1 \leq N \leq 10^6\)
 \(10^3 \leq A[i] \leq 10^3\)
Output Format
Print the array of the squares of each number, also in sorted nondecreasing order.
Solutions
The naive solution consists in creating an array of the squares of each element, and sort them:


A variation consists in mapping the squared vector into a sorted data structure and map it back to a vector:


Clearly, such solutions are both order of \(O(N \cdot LogN)\). The latter is even worse since is uses more space.
We asked to find a linear time algorithm.
A more clever solution comes with an intuition: the array might have a negative part and a following positive part. We can iterate both at the same time, adding to the result array the lowest value for each iteration.
First of all, we need to find the beginning of the positive values. This is a simple array find. Then, we can set two indexes: one moving backwards from the last negative value, and one moving forward from the first positive value.
At every step, we choose which element has the lowest magnitude and add its square to the output array (we print it). We move one of the two indexes accordingly.
Here is a C++ implementation:


An alternative solution runs in a single pass and still consists in using two indexes but we start filling the result array backwards this time.
We start comparing the absolute value of the first and the last element:
 if the leftmost is bigger, then we add the square of the rightmost and move the right index back by one
 otherwise, we add the square of the leftmost and move the left index up by one
Here is the implementation:


Another approach using two lists by Eduard “Eddie” Rubio Cholbi and Stefano Ligabue:


The idea is to fill two lists, one with the square of positive values and one with the square of negative values, and then merge them together (since they are sorted).
Note the pearl of wisdom: using the selector inside the array access operator to select the former or the latter array depending on the sign of the current value.
After seeing this soluton at the retrospective in Modena (April 2019), Marco Arena had an insight and he wrote a very similar solution in C++ that is totally inplace:


This snippet is a tribute to the flexibility of the C++ standard library.