Browse curriculum

Squares of a Sorted Array

Return the sorted squares of a sorted array in O(n): the largest square is always at one end, so fill the output from the back with two pointers.

Problem Understanding

Squares of a Sorted Array: given an array sorted in non-decreasing order, return the squares of each number, also sorted.

Example: [-4, -1, 0, 3, 10] returns [0, 1, 9, 16, 100]. Squaring in place gives [16, 1, 0, 9, 100], which is no longer sorted because of the negatives.

The Intuition: The Biggest Square Is on the Outside

Negatives break the order: -4 is smaller than 3, but its square is larger. What stays true is that squares grow with absolute value, and in a sorted array the largest absolute values sit at the two ends.

So use two pointers, one at each end, and build the answer from the largest square down:

  1. Compare |nums[lo]| and |nums[hi]|.
  2. Write the larger one's square to the last free slot of the output.
  3. Move that pointer inward and repeat.

It is the same back-to-front fill as Merge Sorted Array: two sorted runs (the negatives reversed, and the positives) merged from the largest end.

Interactive Walkthrough

The values still between lo and hi are shaded. Each step, the end with the larger absolute value wins: its square drops into the output at k, which fills from the right.

Dry Run Table

Input: [-4, -1, 0, 3, 10]

lo hi Compare Write k
-4 10 4 < 10 100 4
-4 3 4 > 3 16 3
-1 3 1 < 3 9 2
-1 0 1 > 0 1 1
0 0 equal 0 0

Result: [0, 1, 9, 16, 100].

The Solution Template

Two pointers from the ends, filling the output from the back.

Squares of a Sorted Array Code
1var sortedSquares = function(nums) {
2 const n = nums.length;
3 const out = new Array(n);
4 let lo = 0, hi = n - 1;
5 for (let k = n - 1; k >= 0; k--) {
6 if (Math.abs(nums[lo]) > Math.abs(nums[hi])) {
7 out[k] = nums[lo] * nums[lo];
8 lo++;
9 } else {
10 out[k] = nums[hi] * nums[hi];
11 hi--;
12 }
13 }
14 return out;
15};

Edge Cases & Common Mistakes

  • All non-negative: the right end always wins; the squares keep their order.
  • All negative: the left end always wins; the output is the input reversed and squared.
  • Filling from the front: the ends give the largest squares, so writing them at the front produces a descending array.
  • Comparing values instead of absolute values: -4 < 3, but 16 > 9.

Summary

Squares grow with absolute value, so the largest square left is always at one end of the sorted array. Compare the two ends, write the larger square into the output from the back, and move that pointer inward. O(n) time.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Point at both ends

    lo = 0, hi = n − 1, and an output array of size n.

  2. Place the larger square

    For k from n − 1 down to 0, compare |nums[lo]| and |nums[hi]|; write the larger square to out[k] and move that pointer inward.

  3. Return the output

    It is filled in increasing order from left to right.

Frequently asked questions

Why not square everything and sort?

That works in O(n log n). The input is already sorted, though, and the follow-up asks for O(n): the two-pointer merge uses the existing order instead of sorting again.


Why is the largest square always at an end?

Squares grow with absolute value. In a sorted array the most negative number is at the left end and the most positive at the right end, so the largest absolute value, and therefore the largest square, is at one of them.


Why fill the output from the back?

The two ends give the largest remaining square at each step, which belongs at the end of the result. Filling from the right means every value is placed directly in its final position.

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description