Computing Sorted Squares of a Non-Decreasing Integer Array

Method 1: Square then Sort

This approach squares each element first and subsequently sorts the resulting array.

#include <stdio.h>
#include <stdlib.h>

int compareElements(const void* first, const void* second) {
  int elemA = *((int*)first);
  int elemB = *((int*)second);
  if (elemA < elemB) return -1;
  if (elemA > elemB) return 1;
  return 0;
}

int* squareAndSort(int* inputArray, int arrLength, int* resultLength) {
  // Square every element in place
  for (int idx = 0; idx < arrLength; idx++) {
    inputArray[idx] = inputArray[idx] * inputArray[idx];
  }
  
  // Perform an in-place sort
  qsort(inputArray, arrLength, sizeof(int), compareElements);
  
  // Set the output size
  *resultLength = arrLength;
  
  return inputArray;
}

int main(void) {
  int sample[] = { -7, -3, 2, 4, 9 };
  int length = sizeof(sample) / sizeof(sample[0]);
  int outputSize;
  int* sortedResult = squareAndSort(sample, length, &outputSize);

  printf("Sorted Squares: ");
  for (int i = 0; i < outputSize; i++) {
    printf("%d ", sortedResult[i]);
  }
  printf("\n");
  return 0;
}

The time complexity for this method is O(n + n log n), dominated by the sorting step.

Method 2: Two-Pointer Technique

Given the input array is sorted in non-decreasing order, squaring can place the largest value at either end, not in the midddle. A two-pointer technique efficient constructs the sorted squares from the outside in.

int* computeSortedSquares(int* numbers, int count, int* outputCount) {
    // Allocate memory for the result
    int* resultArray = malloc(sizeof(int) * count);
    *outputCount = count;
    int left = 0;
    int right = count - 1;
    int insertPos = count - 1;

    while (left <= right) {
        int sqLeft = numbers[left] * numbers[left];
        int sqRight = numbers[right] * numbers[right];
        
        // Place the larger square at the current insertion position
        if (sqLeft > sqRight) {
            resultArray[insertPos] = sqLeft;
            left++;
        } else {
            resultArray[insertPos] = sqRight;
            right--;
        }
        insertPos--;
    }
    return resultArray;
}

This approach runs in O(n) time with O(n) auxiliary space.

Method 3: Merge Strategy Using Partition

First, locate the index separating non-negative and negative numbers. The squares of the neagtive portion are in decreasing order, while the squares of the non-negative portion are in increasing order. Merge these two sorted sequences.

int* mergeSortedSquares(int* numbers, int count, int* outputCount) {
  // Find the last index of a negative number
  int splitIdx = -1;
  for (int i = 0; i < count; ++i) {
    if (numbers[i] < 0) {
      splitIdx = i;
    } else {
      break;
    }
  }

  int* finalArray = malloc(sizeof(int) * count);
  *outputCount = 0;
  int neg = splitIdx;          // Pointer for negative segment (moves left)
  int nonNeg = splitIdx + 1;   // Pointer for non-negative segment (moves right)

  while (neg >= 0 || nonNeg < count) {
    if (neg < 0) {
      // Exhausted negative segment
      finalArray[(*outputCount)++] = numbers[nonNeg] * numbers[nonNeg];
      ++nonNeg;
    } else if (nonNeg >= count) {
      // Exhausted non-negative segment
      finalArray[(*outputCount)++] = numbers[neg] * numbers[neg];
      --neg;
    } else {
      // Compare squares from both segments
      int sqNeg = numbers[neg] * numbers[neg];
      int sqNonNeg = numbers[nonNeg] * numbers[nonNeg];
      if (sqNeg < sqNonNeg) {
        finalArray[(*outputCount)++] = sqNeg;
        --neg;
      } else {
        finalArray[(*outputCount)++] = sqNonNeg;
        ++nonNeg;
      }
    }
  }
  return finalArray;
}

Tags: Arrays Sorting algorithms two-pointer c-programming

Posted on Fri, 15 May 2026 09:48:25 +0000 by prc