977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路
这道题如果暴力的话就比较简单:把所有数平方后,在使用排序函数就行了。但如果想满足题目的时间复杂度:O(n)的话,就必须使用双指针来解决。
双指针具体思路:平方数最大的数只会出现在最左边的负数或者最右边的正数,所以我们使用左右两个指针来获取最大值,当获取值后,对指针进行左移或者右移。
代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left=0;
int right=nums.size()-1;
vector <int> res;
while(left<=right){
if(abs(nums[left])<=abs(nums[right])){
res.push_back(nums[right]*nums[right]);
right--;
}
else{
res.push_back(nums[left]*nums[left]);
left++;
}
}
reverse(res.begin(),res.end());
return res;
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(1)
209.长度最小的子数组
给定一个含有
n
个正整数的数组和一个正整数target
。找出该数组中满足其和
≥ target
的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回0
。
思路
最直观的思路是使用暴力算法:从第一位开始计算满足条件的数组最小长度,然后移动到下一位继续进行计算,直至移动到最后一位。但必定会超时,所以需要进行优化。
优化思路是使用双指针(滑动窗口)算法,具体流程请看思路讲解。
代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int res= 1000000;
int slowindex=0;
int fastindex=0;
int sum=0;
for(;fastindex<nums.size();fastindex++)
{
sum+=nums[fastindex];
while(sum>=target){
res=min(fastindex-slowindex+1,res);
sum-=nums[slowindex++];
}
}
if(res==1000000)
return 0;
return min(fastindex-slowindex+1,res);
}
};
查看讲解后,发现res初始化为INT32_MAX更合适。
复杂度
时间复杂度:O(n)
空间复杂度:O(1)
59.螺旋矩阵
给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
思路
思路比较简单,但代码编写有太多细节需要注意,会遇到许多问题,需要注意:
- 这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则(不使用左闭右闭的原则是因为在该原则下,相邻的两条边会出现重复元素),这样这一圈才能按照统一的规则画下来。我在这使用左闭右开的原则。
- 需要确定循环次数(n/2)、每一条边的遍历长度(n-循环次数),以及是否需要为中间那个方格赋值(n为奇数还是偶数)。
代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int mid=n/2;
int loop=n/2;
int l=0;
int w=0;
int i=0,j=0;
int count=0;
int offset=1;
while(loop--){
i=l;
j=w;
for(j=w;j<n-offset;j++){
res[i][j]=++count;
}
for(i=l;i<n-offset;i++){
res[i][j]=++count;
}
for(;j>w;j--){
res[i][j]=++count;
}
for(;i>l;i--){
res[i][j]=++count;
}
l++;
w++;
offset++;
}
if(n%2!=0){
res[mid][mid]=++count;
}
return res;
}
};
复杂度
时间复杂度:O(n^2)(遍历二维数组的时间)