题目地址:
https://leetcode.com/problems/sort-transformed-array/
给定一个二次整系数多项式 f f f,再给定一个整数数组 A A A,已经按升序排好序,要求返回数组 f ( A ) f(A) f(A)并且也按升序排序,并且要求 O ( n ) O(n) O(n)时间复杂度。
由初中数学知识知道,当抛物线开口向上时,最大值在区间端点取到,而若开口向下时,最小值在区间端点取到。所以可以用对撞双指针,如果开口向上,则把最大、次大等等存入最终结果,返回前反个序即可;若开口向下,则把最小、次小等等存入最终结果,直接返回。注意到题目没说 a a a一定是 0 0 0,但如果 a a a是 0 0 0的话,抛物线退化为直线,等同于开口向下的做法,所以代码里只需注意将其归结为 a < 0 a<0 a<0的情况去做即可。代码如下:
public class Solution {
public int[] sortTransformedArray(int[] nums, int a, int b, int c) {
if (nums == null || nums.length == 0) {
return nums;
}
int[] res = new int[nums.length];
int idx = 0;
int i = 0, j = nums.length - 1;
while (i <= j) {
int f1 = f(nums[i], a, b, c), f2 = f(nums[j], a, b, c);
// 开口向上,按从大到小的顺序存入res
if (a > 0) {
if (f1 >= f2) {
res[idx++] = f1;
i++;
} else {
res[idx++] = f2;
j--;
}
} else {
// 否则若开口向下或者退化为直线,则按从小到大的顺序存入res
if (f1 <= f2) {
res[idx++] = f1;
i++;
} else {
res[idx++] = f2;
j--;
}
}
}
// 如果开口向上还需要给数组反个序
if (a > 0) {
reverse(res);
}
return res;
}
private void reverse(int[] nums) {
int i = 0, j = nums.length - 1;
while (i < j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
i++;
j--;
}
}
private int f(int x, int a, int b, int c) {
return a * x * x + b * x + c;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。