算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
今天和大家聊的问题叫做 有序转化数组,我们先来看题面:https://leetcode-cn.com/problems/sort-transformed-array/
Given a sorted array of integers nums and integer values a, band c. Apply a quadratic function of the form f(x) = ax2 + bx + c to each element x in the array.The returned array must be in sorted order.
Expected time complexity: O(n)
给你一个已经 排好序 的整数数组 nums 和整数 a、b、c。对于数组中的每一个数 x,计算函数值 f(x) = ax2 + bx + c,请将函数值产生的数组返回。要注意,返回的这个数组必须按照 升序排列,并且我们所期望的解法时间复杂度为 O(n)。
示例
示例 1:
输入: nums = [-4,-2,2,4], a = 1, b = 3, c = 5
输出: [3,9,15,33]
示例 2:
输入: nums = [-4,-2,2,4], a = -1, b = 3, c = 5
输出: [-23,-5,1,7]
解题
主要思路:(1)理解二次曲线的开口方向对整个输入数组对应的结果的单调性的影响是关键点,而二次曲线的开口方向是由变量a的正负确定的;(2)故分情况讨论,开口向下时,使用双指针,从两端到中间遍历,将找到的较小值从0的位置开始,放到结果数组中;(3)开口向上时,使用双指针,从两端到中间遍历,将找到的较大值从 nums.size()-1 的位置开始,放到结果数组中;
class Solution {
public:
vector<int> sortTransformedArray(vector<int>& nums, int a, int b, int c) {
vector<int> res(nums.size(),0);
int left=0;
int right=nums.size()-1;
for(int& n:nums){//先计算出各个元素对应的值
n=a*n*n+b*n+c;
}
//开口向上
if(a>0){
//从数组中的较大值从 nums.size()-1 的位置开始,逐个的放入结果数组中
int pos=nums.size()-1;
while(left<=right){
if(nums[left]<=nums[right]){
res[pos--]=nums[right--];
}
else{
res[pos--]=nums[left++];
}
}
}
else{
//从数组中的较小值从 0 的位置开始,逐个的放入结果数组中
int pos=0;
while(left<=right){
if(nums[left]<=nums[right]){
res[pos++]=nums[left++];
}
else{
res[pos++]=nums[right--];
}
}
}
return res;//返回结果
}
};