🧠
Two Pointers with Parabola Shape (Optimal O(n))
💡 This approach leverages the parabola shape of the quadratic function and the sorted input to build the output in O(n) time without sorting.
Intuition
Because nums is sorted, and f(x) = ax^2 + bx + c is a parabola, the transformed values will be largest at the ends if a > 0 or smallest at the ends if a < 0. Use two pointers at the ends and fill the output array from the appropriate end.
Algorithm
- Define a helper function to compute f(x) = ax^2 + bx + c.
- Initialize two pointers: left at start, right at end of nums.
- Create an output array of the same length.
- If a >= 0, fill output from the end; else fill from the start.
- Compare f(nums[left]) and f(nums[right]) and place the larger (or smaller) at the current output position.
- Move pointers inward and output index accordingly until left > right.
- Return the output array.
💡 This algorithm cleverly uses two pointers and the parabola shape to fill the output in sorted order without sorting.
from typing import List
def sortTransformedArray(nums: List[int], a: int, b: int, c: int) -> List[int]:
def quad(x):
return a * x * x + b * x + c
n = len(nums)
result = [0] * n
left, right = 0, n - 1
index = n - 1 if a >= 0 else 0
step = -1 if a >= 0 else 1
while left <= right:
left_val = quad(nums[left])
right_val = quad(nums[right])
if a >= 0:
if left_val > right_val:
result[index] = left_val
left += 1
else:
result[index] = right_val
right -= 1
index += step
else:
if left_val < right_val:
result[index] = left_val
left += 1
else:
result[index] = right_val
right -= 1
index += step
return result
# Driver code
if __name__ == "__main__":
print(sortTransformedArray([-4, -2, 2, 4], 1, 3, 5)) # Output: [3, 9, 15, 33]
print(sortTransformedArray([-4, -2, 2, 4], -1, 3, 5)) # Output: [-23, -5, 1, 7]
Line Notes
def quad(x):Defines quadratic function for reuse
left, right = 0, n - 1Initialize two pointers at array ends
index = n - 1 if a >= 0 else 0Decide output fill direction based on parabola shape
while left <= right:Loop until pointers cross to process all elements
import java.util.*;
public class Solution {
public static int[] sortTransformedArray(int[] nums, int a, int b, int c) {
int n = nums.length;
int[] result = new int[n];
int left = 0, right = n - 1;
int index = a >= 0 ? n - 1 : 0;
int step = a >= 0 ? -1 : 1;
while (left <= right) {
int leftVal = a * nums[left] * nums[left] + b * nums[left] + c;
int rightVal = a * nums[right] * nums[right] + b * nums[right] + c;
if (a >= 0) {
if (leftVal > rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
} else {
if (leftVal < rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
}
}
return result;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(sortTransformedArray(new int[]{-4, -2, 2, 4}, 1, 3, 5)));
System.out.println(Arrays.toString(sortTransformedArray(new int[]{-4, -2, 2, 4}, -1, 3, 5)));
}
}
Line Notes
int left = 0, right = n - 1;Initialize two pointers at array ends
int index = a >= 0 ? n - 1 : 0;Set output fill index based on parabola direction
while (left <= right) {Process elements until pointers cross
if (a >= 0) {Handle parabola opening upwards case
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> sortTransformedArray(vector<int>& nums, int a, int b, int c) {
int n = nums.size();
vector<int> result(n);
int left = 0, right = n - 1;
int index = (a >= 0) ? n - 1 : 0;
int step = (a >= 0) ? -1 : 1;
auto quad = [&](int x) { return a * x * x + b * x + c; };
while (left <= right) {
int leftVal = quad(nums[left]);
int rightVal = quad(nums[right]);
if (a >= 0) {
if (leftVal > rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
} else {
if (leftVal < rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
}
}
return result;
}
int main() {
vector<int> nums = {-4, -2, 2, 4};
vector<int> res1 = sortTransformedArray(nums, 1, 3, 5);
for (int v : res1) cout << v << " "; // 3 9 15 33
cout << endl;
vector<int> res2 = sortTransformedArray(nums, -1, 3, 5);
for (int v : res2) cout << v << " "; // -23 -5 1 7
cout << endl;
return 0;
}
Line Notes
int left = 0, right = n - 1;Initialize pointers at array ends
int index = (a >= 0) ? n - 1 : 0;Set output index based on parabola shape
while (left <= right) {Loop until pointers cross
if (a >= 0) {Handle parabola opening upwards case
function sortTransformedArray(nums, a, b, c) {
function quad(x) {
return a * x * x + b * x + c;
}
const n = nums.length;
const result = new Array(n);
let left = 0, right = n - 1;
let index = a >= 0 ? n - 1 : 0;
const step = a >= 0 ? -1 : 1;
while (left <= right) {
const leftVal = quad(nums[left]);
const rightVal = quad(nums[right]);
if (a >= 0) {
if (leftVal > rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
} else {
if (leftVal < rightVal) {
result[index] = leftVal;
left++;
} else {
result[index] = rightVal;
right--;
}
index += step;
}
}
return result;
}
// Driver code
console.log(sortTransformedArray([-4, -2, 2, 4], 1, 3, 5)); // [3, 9, 15, 33]
console.log(sortTransformedArray([-4, -2, 2, 4], -1, 3, 5)); // [-23, -5, 1, 7]
Line Notes
function quad(x) {Defines quadratic function for reuse
let index = a >= 0 ? n - 1 : 0;Determines output fill direction based on parabola
while (left <= right) {Processes elements until pointers cross
if (a >= 0) {Handles parabola opening upwards case
Each element is processed once with two pointers, no sorting needed.
💡 For n=100,000, this means about 100,000 operations, which is efficient and fast.
Interview Verdict: Accepted and optimal
This is the best approach to implement in interviews for efficiency and clarity.