给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
最简单的思路,就地将数组元素平方然后进行排序,但是时间复杂度是排序的时间复杂度这里用的是C++提供的快速排序,时间复杂度O(nlogn),空间复杂度O(1)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<nums.size();i++)
{
nums[i]*=nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
因为时间复杂度较高想要降低时间复杂度为O(n)级别,因为没有排序满足要求所以要换一个思路,这里选择用空间换时间引入一个结果集,因为如果元素是全是正数那么不需要排序,所以是负数元素影响了顺序,而负数越小那么平方越大所以只用比较最左边的元素平方和最右边元素平方的大小把大的放入结果集最后面即可这里可以容易地想到使用双指针
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int l=0,r=nums.size()-1;
int k=r;
vector<int> res(nums.size(),0);
while(l<=r)
{
if(nums[l]*nums[l]<nums[r]*nums[r])
{
res[k]=nums[r]*nums[r];
k--;
r--;
}
else
{
res[k]=nums[l]*nums[l];
k--;
l++;
}
}
return res;
}
};
时间复杂度O(n),空间复杂度O(n)
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
看到这道题最简单的思路一定就是暴力解法两重for循环,但是
1 <= nums.length <= 105
length长度很大如果使用时间复杂度为O(n^2)的算法很显然要超时但是这里也提供一个暴力思路代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length=INT_MAX;
for(int i=0;i<nums.size();++i)
{
int sum=0;
int l=0;
bool flag=false;
int x=i;
while(sum<target&&x<nums.size())
{
sum+=nums[x];
l++;
x++;
if(sum>=target)flag=true;
}
if(!flag)break;
length=min(length,l);
}
if(length==INT_MAX)length=0;
return length;
}
};
时间复杂度 O(n^2) 空间复杂度O(1)
暴力解题不行就要想别的算法,其实我们暴力解法有很多重复的操作
最外层for循环每遍历一次我们就要从当前位置加到sum>=target的位置,那么有没有一种方法可以省略这些操作呢?
我们可以考虑最常用的方法用空间换时间,我们可以看作把增加的元素放入一个队列里面,当队列里面的元素综合大于等于目标数就可以把队头抛出,在队尾添加元素,直到再次大于等于,这就是滑动窗口法,但这里其实可以省略队列,只用sum表示即可
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length=INT_MAX;
int l;
int sum=0;
int j=0;//滑动窗口起始位置
for(int i=0;i<nums.size();++i)
{
sum+=nums[i];
while(sum>=target)
{
l=(i-j+1);
length=min(length,l);
sum-=nums[j];
j++;//滑动窗口初始位置增加
}
}
if(length==INT_MAX)length=0;
return length;
}
};
时间复杂度 O(n) 空间复杂度 O(1)