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.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Easy

๐Ÿ”—

LeetCode

Problem #977

๐Ÿ—๏ธ

Pattern

Two Pointers โ€” compare absolutes from ends

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.

Example 1
Input: nums = [-4, -1, 0, 3, 10] Output: [0, 1, 9, 16, 100] // (-4)ยฒ=16, (-1)ยฒ=1, 0ยฒ=0, 3ยฒ=9, 10ยฒ=100 โ†’ sorted: [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โด โ€ข -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; class Solution { public int[] 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
class Solution: def sortedSquares(self, nums: list[int]) -> list[int]: return sorted(x * x for x in nums)
MetricValue
TimeO(n log n) โ€” dominated by sort
SpaceO(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
INPUT (sorted) -4 -1 0 3 10 L R pos=4: |โˆ’4|=4 vs |10|=10 โ†’ 10ยฒ = 100 at result[4], R-- pos=3: |โˆ’4|=4 vs |3|=3 โ†’ (โˆ’4)ยฒ = 16 at result[3], L++ pos=2: |โˆ’1|=1 vs |3|=3 โ†’ 3ยฒ = 9 at result[2], R-- pos=1: |โˆ’1|=1 vs |0|=0 โ†’ (โˆ’1)ยฒ = 1 at result[1], L++ pos=0: L==R, 0ยฒ = 0 at result[0] โ†’ DONE RESULT (filled right to left) 0 1 9 16 100 Answer: [0, 1, 9, 16, 100] โœ“
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
class Solution { public int[] sortedSquares(int[] nums) { int n = nums.length; int[] result = new int[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
class Solution: def sortedSquares(self, nums: list[int]) -> list[int]: n = len(nums) result = [0] * n left, right, pos = 0, n - 1, n - 1 while left <= right: l_sq = nums[left] ** 2 r_sq = nums[right] ** 2 if l_sq > r_sq: result[pos] = l_sq left += 1 else: result[pos] = r_sq right -= 1 pos -= 1 return result
06
Section Six ยท Analysis

Complexity Analysis

ApproachTimeSpaceTrade-off
Square + SortO(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

CaseInputWhy 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.

โ† Back to Two Pointers problems