EasyTwo Pointers

Squares of a Sorted Array โ€” Solution

Problem

You're given an array of integers sorted in non-decreasing order (including negatives). Return a new array containing the square of each number, also in non-decreasing order.

  • Input: nums = [-4, -1, 0, 3, 10]
  • Output: [0, 1, 9, 16, 100]
  • Explanation: Squaring gives [16, 1, 0, 9, 100]; sorted, that's [0, 1, 9, 16, 100]

Counter-example showing why you can't just square left-to-right: [-7, -3, 2, 4] โ†’ squares are [49, 9, 4, 16], which is neither sorted nor trivially fixable without a comparison step.

Intuition

After squaring, large values can come from either end of the array โ€” the most negative numbers and the most positive numbers both produce large squares. So instead of squaring and re-sorting, we can use two pointers starting at opposite ends, always picking the larger square and placing it at the back of the result array. This fills the answer from largest to smallest in a single pass.

Approach 1 โ€” Sort After Squaring

Square every element, then sort. Simple and correct, but pays the O(n log n) cost of sorting even though the input was already in a useful order.

  1. Build a new array by squaring each element.
  2. Sort the squared array and return it.
1def sortedSquares(nums: list[int]) -> list[int]:
2    return sorted(x * x for x in nums)

Time: O(n log n) โ€” dominated by the sort step.

Space: O(n) โ€” the output array.

Approach 2 โ€” Two Pointers (Optimal)

The largest square at any moment is always at one of the two ends of the remaining input range. Use left and right pointers that move inward, placing the larger square at the back of the result array and working toward the front.

  1. Initialize left = 0, right = n - 1, write_index = n - 1.
  2. While left <= right:
    • Compute left_sq = nums[left]ยฒ and right_sq = nums[right]ยฒ.
    • Place the larger of the two at result[write_index] and advance the corresponding pointer inward.
    • Decrement write_index.
  3. Return result.
1def sortedSquares(nums: list[int]) -> list[int]:
2    n = len(nums)
3    result = [0] * n
4    left, right = 0, n - 1
5    write_index = n - 1
6
7    while left <= right:
8        left_sq = nums[left] * nums[left]
9        right_sq = nums[right] * nums[right]
10        if left_sq >= right_sq:
11            result[write_index] = left_sq
12            left += 1
13        else:
14            result[write_index] = right_sq
15            right -= 1
16        write_index -= 1
17
18    return result

Time: O(n) โ€” each element is visited exactly once.

Space: O(n) โ€” the output array; no extra structures needed.

Complexity Summary

ApproachTimeSpaceWhen to use
Sort After SquaringO(n log n)O(n)When brevity matters and performance is not critical
Two PointersO(n)O(n)Always when you want the optimal solution

Common Mistakes

  • Filling the result from the front instead of the back โ€” if you pick the largest square and write it to result[0], you'd need to shift everything; writing from the back avoids this entirely.
  • Using left < right instead of left <= right โ€” when both pointers converge on the same element (e.g., a single middle element), left < right exits too early and skips that element.
  • Forgetting that squaring a negative makes it positive and potentially large โ€” it's tempting to assume the sorted order of absolute values follows the input order, but -7 has a larger square than 3 even though it's earlier in the array.
  • Comparing the raw values instead of their squares โ€” the pointers should compare nums[left]ยฒ vs nums[right]ยฒ, not abs(nums[left]) vs abs(nums[right]). Both are equivalent, but computing the square directly avoids an extra function call and makes the intent clear.
  • Integer overflow in Java/C++ for large inputs โ€” squaring a 32-bit integer at its boundary (ยฑ46341) overflows int. In practice LeetCode's constraints keep values within safe range, but in production code consider using long for intermediate results.

Related Problems

  • 3sum โ€” sorting and using multiple pointers from both ends of an array
  • two-sum-ii-input-array-is-sorted โ€” two pointers on a sorted array converging toward a target
  • container-with-most-water โ€” left/right pointers advancing based on which side limits the answer
  • merge-sorted-array โ€” filling a result array from the back to avoid overwriting unread values
  • sort-colors โ€” in-place rearrangement of an array using multiple pointer techniques

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’