Your solution
If I wanted to do the obvious solution of squaring the array and sorting it it would look something like this:
#include <algorithm>
#include <iostream>
int main(){
//arguably arr should be an std::array or even auto for an std::initializer_list
int arr[] = { -3, -2, 0, 4, 5, 8 };
//square array
std::transform(std::begin(arr), std::end(arr), std::begin(arr),
[](int n){ return n * n; }
);
//sort array
std::sort(std::begin(arr), std::end(arr));
//print result
for (const auto &i : arr)
std::cout << i << ' ';
}
Was it a requirement to not use the standard library? It saves you from some of the pain of implementing boring, difficult and error-prone things such as sorting-algorithms.
My solution
The problem with squaring the array is that negative numbers become positive, making the array not sorted anymore. My idea is to find the index mid
of the first non-negative number and then squaring the whole array. The partial list [begin, mid[
is sorted in reverse order and the partial list ]mid, end[
is already correctly sorted. Two sorted lists can be efficiently std::merge
d into a sorted list. The reverse ordering of the first list can be compensated by using a reverse_iterator
.
#include <algorithm>
#include <iostream>
int main(){
int arr[] = { -3, -2, 0, 4, 5, 8 };
//find index of first non-negative element
auto midIndex = std::lower_bound(std::begin(arr), std::end(arr), 0);
//square array
std::transform(std::begin(arr), std::end(arr), std::begin(arr),
[](int n){ return n * n; }
);
//new array of same size and type as old array
decltype(arr) squareArray;
//merge left list [begin, midIndex] and right list [midIndex, end[
std::merge(
//left list
std::reverse_iterator<decltype(midIndex)>(midIndex), std::rend(arr),
//right list
midIndex, std::end(arr),
//destination
squareArray
);
//print result
for (const auto &i : squareArray)
std::cout << i << ' ';
}
This implementation uses a second array for the merged list. It is probably possible to do it in-place, but that requires some more effort. My solution reduced the complexity from O(n*log(n)) to O(n), but changed the space complexity from O(1) to O(n), which is not strictly necessary. I would probably favor your solution because it is easy unless it is proven by profiling that the small efficiency deficit is a significant problem.
{-3,-2,0,4,5,8};
Reading is tech. ( and an int type can be negative, unless otherwise specified ) \$\endgroup\$(-1;+1)
range. \$\endgroup\$