LC 977 ยท Squares of a Sorted Array โ Solution & Explanation | DSA Guide
Two approaches to LeetCode Squares of a Sorted Array โ sort after squaring O(n log n) and optimal two-pointer O(n). Java and Python solutions with visual walkthrough.
LeetCode ยท #977
Squares of a Sorted Array Solution
Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number, also sorted in non-decreasing order. The input may contain negative numbers, so squaring can change the relative order.
โข 1 โค nums.length โค 10โดโข -10โด โค nums[i] โค 10โดโข nums is sorted in non-decreasing order โ Key: already sorted โ the largest squares are at the ENDS
02
Section Two ยท Approach 1
Brute Force โ Square & Sort O(n log n)
Square every element, then sort the result. Simple and correct, but doesn't exploit the fact that the input is already sorted.
Why we can do better
Problem: Sorting costs O(n log n). The input is already sorted โ the largest squares must be at either end (largest negatives or largest positives). Two pointers from both ends can build the result in O(n) by always picking the larger square.
Java โ Square + Sort
import java.util.Arrays;
classSolution {
publicint[] sortedSquares(int[] nums) {
for (int i = 0; i < nums.length; i++)
nums[i] = nums[i] * nums[i];
Arrays.sort(nums);
return nums;
}
}
Python โ Square + Sort
classSolution:
defsortedSquares(self, nums: list[int]) -> list[int]:
return sorted(x * x for x in nums)
Metric
Value
Time
O(n log n) โ dominated by sort
Space
O(1) or O(n) depending on sort
03
Section Three ยท Approach 2
Two Pointers โ O(n)
Since the input is sorted, the largest squared values are at the extremes โ either the most negative (left end) or the most positive (right end). Use two pointers from both ends, compare absolute values, and fill the result array from right to left (largest to smallest).
๐ก Mental model: Imagine two runners at opposite ends of a number line. Each holds their squared value like a price tag. A judge compares their tags โ the bigger one gets placed at the back of the podium. That runner steps inward. The judge fills the podium back-to-front with decreasing squares.
Algorithm
Step 1: Create result array of size n. Set left = 0, right = n - 1, pos = n - 1.
Step 2: While left โค right: compare |nums[left]| with |nums[right]|.
Step 3: Place the larger square at result[pos--]. Advance the pointer whose value was used.
Step 4: Return result.
๐ฏ When to recognize this pattern:
When the input is sorted and the desired output depends on absolute values or values that "mirror" around zero โ the extremes hold the largest magnitudes.
Filling the result from the outside-in (or back-to-front) lets you avoid re-sorting.
This specific pattern is unique to LC 977 but the general idea of "sorted input โ two-pointer merge from ends" is widely applicable.
04
Section Four ยท Trace
Visual Walkthrough
Trace through nums = [-4, -1, 0, 3, 10]:
Two Pointers โ fill result from right to left
Notice:
We fill the result from the back (largest first).
The two pointers ensure we always pick the largest remaining square. Each element is visited exactly once โ O(n).
05
Section Five ยท Implementation
Code โ Java & Python
Java โ Two Pointers from ends
classSolution {
publicint[] sortedSquares(int[] nums) {
int n = nums.length;
int[] result = newint[n];
int left = 0, right = n - 1, pos = n - 1;
while (left <= right) {
int lSq = nums[left] * nums[left];
int rSq = nums[right] * nums[right];
if (lSq > rSq) {
result[pos--] = lSq;
left++;
} else {
result[pos--] = rSq;
right--;
}
}
return result;
}
}
Python โ Two Pointers from ends
classSolution:
defsortedSquares(self, nums: list[int]) -> list[int]:
n = len(nums)
result = [0] * n
left, right, pos = 0, n - 1, n - 1while left <= right:
l_sq = nums[left] ** 2
r_sq = nums[right] ** 2if l_sq > r_sq:
result[pos] = l_sq
left += 1else:
result[pos] = r_sq
right -= 1
pos -= 1return result
06
Section Six ยท Analysis
Complexity Analysis
Approach
Time
Space
Trade-off
Square + Sort
O(n log n)
O(1)*
Doesn't use sorted-input property. *In-place sort.
Two Pointers โ optimal
O(n)
O(n)
Linear scan; O(n) for the result array (required by output)
Space note:
The O(n) space is for the output array โ required by the problem. No additional space beyond that.
If you count only auxiliary space, it's O(1).
07
Section Seven ยท Edge Cases
Edge Cases & Pitfalls
Case
Input
Why It Matters
All non-negative
[0, 1, 2, 3]
Already sorted after squaring. Right pointer dominates.
All negative
[-3, -2, -1]
Squaring reverses the order. Left pointer dominates.
Single element
[5]
Result is [25]. One iteration, left == right.
Zeros
[-2, 0, 0, 3]
0ยฒ = 0 ends up at the front. Works naturally.
Same absolute values
[-3, 3]
Both square to 9. The else branch handles ties โ either order is fine since values are equal.
โ Common Mistake: Filling the result array from left to right (smallest first) instead of right to left. The two pointers identify the largest remaining square โ so you must fill from the back. Filling from the front would require knowing the smallest square, which needs a different pointer setup.