977. Squares of a Sorted Array - Explanation
Description
You are given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
Example 1:
Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]Explanation: After squaring, the array becomes [16,1,0,9,100].
After sorting, it becomes [0,1,9,16,100].
Example 2:
Input: nums = [-7,-3,2,3,11]
Output: [4,9,9,49,121]Constraints:
1 <= nums.length <= 10,000-10,000 <= nums[i] <= 10,000numsis sorted in non-decreasing order.
Follow up: Squaring each element and sorting the new array is very trivial, could you find an O(n) solution using a different approach?
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Two Pointers Technique - Used to compare elements from both ends of the sorted array simultaneously
- Sorting Algorithms - Understanding time complexity trade-offs between sorting vs. linear approaches
- Absolute Values - Recognizing that negative numbers become positive when squared, affecting order
1. Sorting
Intuition
The straightforward approach is to square each element first and then sort the result. While the original array is sorted, squaring can change the order since negative numbers become positive. For example, [-4, -1, 0, 3] becomes [16, 1, 0, 9] after squaring, which needs to be sorted to [0, 1, 9, 16].
Algorithm
- Iterate through the array and square each element in place.
- Sort the array using the built-in sort function.
- Return the sorted array of squares.
Time & Space Complexity
- Time complexity:
- Space complexity: or depending on the sorting algorithm.
2. Two Pointers - I
Intuition
Since the input array is sorted, the largest squares will be at either end (the most negative or most positive values). By using two pointers at both ends, we can compare absolute values and always pick the larger square. This builds the result in descending order, which we then reverse.
Algorithm
- Initialize two pointers:
lat the start andrat the end of the array. - Create an empty
resultlist. - While
l <= r:- Compare the squares of
nums[l]andnums[r]. - Append the larger square to the
resultand move the corresponding pointer inward.
- Compare the squares of
- Reverse the
resultarray (since we collected largest to smallest). - Return the reversed
result.
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l, r, res = 0, len(nums) - 1, []
while l <= r:
if (nums[l] * nums[l]) > (nums[r] * nums[r]):
res.append(nums[l] * nums[l])
l += 1
else:
res.append(nums[r] * nums[r])
r -= 1
return res[::-1]Time & Space Complexity
- Time complexity:
- Space complexity: for the output array.
3. Two Pointers - II
Intuition
This is an optimization of the previous approach that avoids the final reversal step. Instead of building the result from smallest to largest and reversing, we fill the result array from the end to the beginning. We still use two pointers to compare the absolute values at both ends, but we place each square directly in its final position.
Algorithm
- Create a
resultarray of the same size as the input. - Initialize
l = 0,r = n - 1, andresIndex = n - 1(pointing to the last position). - While
l <= r:- Compare the absolute values of
nums[l]andnums[r]. - Place the larger square at
res[resIndex]and move the corresponding pointer. - Decrement
resIndex.
- Compare the absolute values of
- Return the
resultarray (no reversal needed).
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
n = len(nums)
res = [0] * n
l, r = 0, n - 1
res_index = n - 1
while l <= r:
if abs(nums[l]) > abs(nums[r]):
res[res_index] = nums[l] * nums[l]
l += 1
else:
res[res_index] = nums[r] * nums[r]
r -= 1
res_index -= 1
return resTime & Space Complexity
- Time complexity:
- Space complexity: for the output array.
Common Pitfalls
Assuming Squares Preserve Sorted Order
A common mistake is assuming that squaring a sorted array keeps it sorted. This is false when negative numbers are present because squaring makes them positive, potentially larger than squared positive numbers. For example, [-4, -1, 0, 3] becomes [16, 1, 0, 9], which is not sorted.
Forgetting to Handle Negative Numbers with Two Pointers
When using two pointers, comparing nums[l] and nums[r] directly instead of their absolute values or squares leads to incorrect results. Negative numbers at the left end may have larger squares than positive numbers at the right end, so always compare absolute values or squared values.
Sign in to join the discussion