Given a sorted array of integers nums and integer values a, b and c. Apply a quadratic function of the form f(x)=ax^2+bx+cf(x)=ax2+bx+c to each element xx in the array.
The returned array must be in sorted order.
Example
Example1
Input: nums = [-4, -2, 2, 4], a = 1, b = 3, c = 5
Output: [3, 9, 15, 33]
Example2
Input: nums = [-4, -2, 2, 4], a = -1, b = 3, c = 5
Output: [-23, -5, 1, 7]
Notice
Expected time complexity: O(n)
分析
这道题最容易想到的解法就是首先计算出所有的结果,然后直接排序,但是复杂度为O(n * logn),不满足题目要求。
这道题如果只是想着找规律很不直观,其实只要画出二次函数的图就能一目了然。
以上图为例,如果a > 0时,二次函数的开口向上,排好序的数组的跨度有三种情况:全在对称轴左边,全在右边,横跨对称轴。但是有一点是不变的,数组的两头所得的结果一定有一个是最大的。利用这个特点,我们使用left,right两个指针分别指向数组首尾,取较大的计算结果,并移动指针。
对于a < 0,二次函数的开口向下,数组两头的结果一定有一个是最小的,利用这个特点,同样使用left, right两个指针分别指向数组首尾,取较小的计算结果,并移动指针。
对于a == 0的情况,一次函数一定是单调的,left,right指针依然适用。
Code
class Solution {
public:
/**
* @param nums: a sorted array
* @param a:
* @param b:
* @param c:
* @return: a sorted array
*/
vector<int> sortTransformedArray(vector<int> &nums, int a, int b, int c) {
// Write your code here
int len = nums.size();
vector<int> res(len, 0);
int left = 0;
int right = len -1;
int i = 0;
while (left <= right)
{
int leftRes = a * (nums[left] * nums[left]) + b * nums[left] + c;
int rightRes = a * (nums[right] * nums[right]) + b * nums[right] + c;
if (a > 0)
{
if (leftRes >= rightRes)
{
res[len - 1 - i] = leftRes;
left ++;
}
else
{
res[len -1 - i] = rightRes;
right --;
}
}
else
{
if (leftRes <= rightRes)
{
res[i] = leftRes;
left ++;
}
else
{
res[i] = rightRes;
right --;
}
}
i ++;
}
return res;
}
};
运行效率
Your submission beats 80.67% Submissions!