class Solution:
def sortTransformedArray(self, nums, a, b, c):
def f(x):
return a * x * x + b * x + c
n = len(nums)
result = [0] * n
left, right = 0, n - 1
idx = n - 1 if a >= 0 else 0
while left <= right:
left_val = f(nums[left])
right_val = f(nums[right])
if a >= 0:
if left_val > right_val:
result[idx] = left_val
left += 1
else:
result[idx] = right_val
right -= 1
idx -= 1
else:
if left_val < right_val:
result[idx] = left_val
left += 1
else:
result[idx] = right_val
right -= 1
idx += 1
return result
class Solution {
public:
vector<int> sortTransformedArray(vector<int>& nums, int a, int b, int c) {
auto f = [&](int x) { return a * x * x + b * x + c; };
int n = nums.size();
vector<int> result(n);
int left = 0, right = n - 1;
int idx = a >= 0 ? n - 1 : 0;
while (left <= right) {
int leftVal = f(nums[left]);
int rightVal = f(nums[right]);
if (a >= 0) {
if (leftVal > rightVal) {
result[idx--] = leftVal;
left++;
} else {
result[idx--] = rightVal;
right--;
}
} else {
if (leftVal < rightVal) {
result[idx++] = leftVal;
left++;
} else {
result[idx++] = rightVal;
right--;
}
}
}
return result;
}
};
class Solution {
private int f(int x, int a, int b, int c) {
return a * x * x + b * x + c;
}
public 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 idx = a >= 0 ? n - 1 : 0;
while (left <= right) {
int leftVal = f(nums[left], a, b, c);
int rightVal = f(nums[right], a, b, c);
if (a >= 0) {
if (leftVal > rightVal) {
result[idx--] = leftVal;
left++;
} else {
result[idx--] = rightVal;
right--;
}
} else {
if (leftVal < rightVal) {
result[idx++] = leftVal;
left++;
} else {
result[idx++] = rightVal;
right--;
}
}
}
return result;
}
}
var sortTransformedArray = function(nums, a, b, c) {
function f(x) {
return a * x * x + b * x + c;
}
let n = nums.length;
let result = new Array(n);
let left = 0, right = n - 1;
let idx = a >= 0 ? n - 1 : 0;
while (left <= right) {
let leftVal = f(nums[left]);
let rightVal = f(nums[right]);
if (a >= 0) {
if (leftVal > rightVal) {
result[idx--] = leftVal;
left++;
} else {
result[idx--] = rightVal;
right--;
}
} else {
if (leftVal < rightVal) {
result[idx++] = leftVal;
left++;
} else {
result[idx++] = rightVal;
right--;
}
}
}
return result;
};
You are given a sorted array of integers nums
and three integer coefficients a
, b
, and c
. You need to apply the quadratic function f(x) = a * x^2 + b * x + c
to each element x
in nums
, and then return the resulting array sorted in ascending order.
nums
is sorted in non-decreasing order.
At first glance, this problem looks like a straightforward mapping: just apply the function to each element and sort the result. However, since nums
is already sorted, and because the quadratic function can either open upwards (a > 0
) or downwards (a < 0
), we can exploit the structure to optimize the solution.
If we were to simply map and sort, it would work but would not be efficient. Instead, we can notice that:
a > 0
, the function is convex (U-shaped), so the largest values are at the ends of nums
.a < 0
, the function is concave (∩-shaped), so the smallest values are at the ends.a == 0
, the function is linear, and the order depends on b
.This means we can use a two-pointer approach, similar to merging two sorted arrays, to construct the result efficiently.
f(x) = a * x^2 + b * x + c
.
left
at the start and right
at the end of nums
.
a
:
a >= 0
: The largest transformed values are at the ends. Fill the result array from the end to the start, comparing f(nums[left])
and f(nums[right])
each time and placing the larger at the end.
a < 0
: The smallest transformed values are at the ends. Fill the result array from the start to the end, placing the smaller of f(nums[left])
and f(nums[right])
at the front.
This approach ensures we only traverse the array once, achieving linear time complexity.
Let's use nums = [-4, -2, 2, 4]
, a = 1
, b = 3
, c = 5
.
f(x) = x^2 + 3x + 5
to each element:f(-4) = 16 - 12 + 5 = 9
f(-2) = 4 - 6 + 5 = 3
f(2) = 4 + 6 + 5 = 15
f(4) = 16 + 12 + 5 = 33
[9, 3, 15, 33]
. But this is not sorted.
f(-4)=9
and f(4)=33
. Place 33 at the end.f(-4)=9
and f(2)=15
. Place 15 next.f(-4)=9
and f(-2)=3
. Place 9 next.f(-2)=3
remains. Place it at the start.
The result is [3, 9, 15, 33]
, which is sorted.
The optimized method is significantly faster for large input sizes.
By leveraging the properties of the quadratic function and the sorted nature of the input array, we avoid unnecessary sorting and achieve a linear time solution. The two-pointer strategy lets us build the result from both ends, ensuring correct order and efficiency. This approach demonstrates the power of combining mathematical insights with algorithmic techniques for elegant and optimal solutions.