数组part02
一、有序数组的平方
法一:暴力,先把每个元素平方再排序,时间复杂度O(n + nlogn)
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 k=nums.size()-1;vector<int> res(nums.size(),0);for(int i=0,j=nums.size()-1;i<=j;){if(nums[i]*nums[i]<nums[j]*nums[j]){res[k--]=nums[j]*nums[j];j--;}else{res[k--]=nums[i]*nums[i];i++;}}return res;}
};
二、长度最小的子数组
法一:暴力,时间复杂度:O(n^2),空间复杂度:O(1)
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int res=INT32_MAX; // 最终结果int sum=0; // 子序列的数值之和int subLength=0; // 子序列长度for(int i=0;i<nums.size();i++){sum=0;for(int j=i;j<nums.size();j++){sum+=nums[j];if(sum>=target){subLength=j-i+1;res=res<subLength?res:subLength;break;}}}return res==INT32_MAX?0:res; }
};
法二:滑动窗口,时间复杂度:O(n),空间复杂度:O(1)
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int res=INT32_MAX;int i=0; // 滑动窗口起始位置int sum=0; // 窗口内元素的和for(int j=0;j<nums.size();j++){sum+=nums[j];while(sum>=target){int subLength=j-i+1; // 取子序列长度res=res<subLength?res:subLength;sum=sum-nums[i];i++; // 更新i,以保证取的长度最小}}return res==INT32_MAX?0:res;}
};
为什么时间复杂度是O(n)。
不是for里放一个while就是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。
三、螺旋矩阵II
类似二分的思想,控制循环不变量,维护的区间始终为左闭右开
时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
空间复杂度 O(1)
class Solution {
public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n,vector<int>(n,0)); // 初始化一个二维数组int startx=0,starty=0; // 定义每循环一个圈的起始位置int loop=n/2; // 有几个圈int mid=n/2; // n为奇数时的矩阵的中间位置int offset=1; // 需要控制每条边的遍历长度,每循环一圈右边界就收缩一位int count=1; // 用来给矩阵中每一个空格赋值int i,j;while(loop--){i=startx;j=starty;// 下面四个for循环就是模拟转了一圈// 模拟填充上行从左到右(左闭右开)for(;j<n-offset;j++) res[i][j]=count++;// 模拟填充右列从上到下(左闭右开)for(;i<n-offset;i++) res[i][j]=count++;// 模拟填充下行从右到左(左闭右开)for(;j>startx;j--) res[i][j]=count++;// 模拟填充左列从下到上(左闭右开)for(;i>startx;i--) res[i][j]=count++;// 下一圈开始后,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)startx++;starty++;// offset 控制每一圈里每一条边遍历的长度offset++;}// 若n为奇数,最后还需要给矩阵的中心单独赋值if(n%2) res[mid][mid]=count;return res;}
};