Given an array of integers A
sorted in non-decreasing order, return an array of the squares of each number, also in sorted non-decreasing order.
Example 1:
Input: [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Example 2:
Input: [-7,-3,2,3,11]
Output: [4,9,9,49,121]
Note:
1 <= A.length <= 10000
-10000 <= A[i] <= 10000
A
is sorted in non-decreasing order.
Since the arry is non-decreasingly sorted, we can use two pointers, either both pointers start from the middle, the negative one goes to the left and the non-negative goes to the right, as the magnitude of numbers increase from the middle,
result[dest++] = A[positive++] if Math.abs(A[negative]) <= Math.abs(A[positve])
result[dest++] = A[negative--] otherwise
Be careful: postive < A.length && negative >= 0, also need to deal with cases when there are more negative or positve left, copy the leftover to the result array.
Time complexity: O(n) two passes
Space complexity: O(n) to store result
class Solution { int findNonNegativeIndex(int[] A) { int index = 0; while( index < A.length && A[index] < 0) { ++index; } return index; } public int[] sortedSquares(int[] A) { int sz = A.length; int[] result = new int[sz]; int nonNegative = findNonNegativeIndex(A); int negative = nonNegative - 1; int destination = 0; while(nonNegative < sz && negative >= 0) { if(Math.abs(A[negative]) >= Math.abs(A[nonNegative])) { result[destination++] = A[nonNegative] * A[nonNegative]; ++nonNegative; } else { result[destination++] = A[negative] * A[negative]; --negative; } } while(nonNegative < sz) { result[destination++] = A[nonNegative] * A[nonNegative]; ++nonNegative; } while(negative >= 0) { result[destination++] = A[negative] * A[negative]; --negative; } return result; } }
Another way, the two pointers start from two ends and walk towards to each other. Save the effort to deal with the extra cases caused by boundary and also the effor to find the divider between positive and negative numbers.
Time complexity: O(n) one pass
Space complexity: O(n) to store result
class Solution { public int[] sortedSquares(int[] A) { int sz = A.length; int[] result = new int[sz]; for(int left = 0, right = sz-1, destination = sz-1; left <= right; ) { if(Math.abs(A[left]) >= Math.abs(A[right])) { result[destination] = A[left] * A[left]; ++left; --destination; } else { result[destination] = A[right] * A[right]; --right; --destination; } } return result; } }
use the destination index as check condition, slightly more concise
class Solution { public int[] sortedSquares(int[] A) { int sz = A.length; int[] result = new int[sz]; for(int left = 0, right = sz-1, destination = sz-1; destination >= 0; --destination) { if(Math.abs(A[left]) >= Math.abs(A[right])) { result[destination] = A[left] * A[left]; ++left; } else { result[destination] = A[right] * A[right]; --right; } } return result; } }