977.有序数组的平方
重点
重点掌握双指针法,数组平方的最大值就在数组的两端,所以在数组两端分别加一个指针,平方后比较大小,时间复杂度是 O(n )。
代码
- 暴力解法
直接对所有元素平方,使用sort排序,时间复杂度是 O(n + nlogn)。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<nums.size();i++){
nums[i]=nums[i]*nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
- 双指针法
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
//第一次错在没有对vector进行赋值或构造
vector<int> result;//也可以直接vector<int> result(nums.size(),0);
result.assign(nums.size(),0);
int k=nums.size()-1;
int i=0,j=nums.size()-1;
while(i<=j){
if(nums[i]*nums[i]<=nums[j]*nums[j]){
result[k--]=nums[j]*nums[j];
j--;
}
else{
result[k--]=nums[i]*nums[i];
i++;
}
}
return result;
}
};
209.长度最小的子数组|滑动窗口
重点
暴力解两个for循环, 对每一个起始位置都往后遍历一遍,一直到有满足条件的子序列,时间复杂度是O(n^2)。
重点是滑动窗口(也是双指针),for循环里表示的是终止位置,向后遍历,满足条件后不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)(每个元素进来操作一次,出去操作一次,2n)。
ps:这个地方我真的想了好久,主要在于有一些子序列根本不会出现,难道不会错过吗?其实不会的,如果那个子序列都能满足条件 ,终止位置一定会在这个子序列的末尾停下的。
代码
- 暴力解法
//程序是对的,但在leetcode是超时的
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int len=INT32_MAX;//int类型最大的数
for(int i=0;i<=nums.size()-1;i++){
int sum=0;
for(int j=i;j<=nums.size()-1;j++){
sum+=nums[j];
if(sum>=target){
len=min(len,j-i+1);
break;//终止当前循环
}
}
}
return len==INT32_MAX?0:len;
}
};
- 滑动窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum=0;
int len=INT32_MAX;//只能大写
int i=0;
for(int j=0;j<=nums.size()-1;j++){
sum+=nums[j];
while(sum>=target){//这里不能写if,起始位置要持续向前移动
len=min(len,j-i+1);
sum-=nums[i];
i++;
}
}
return len==INT32_MAX?0:len;
}
};
59.螺旋矩阵II
重点
螺旋矩阵其实不涉及什么算法,唯独就是容易绕,边界条件要遵循循环不变量。如果矩阵的边长是n,则需要绕n/2圈,一圈四条边,每一条边都要左闭右开。模拟遍历二维矩阵时间复杂度 O(n^2)。
代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//注意这个vector二维数组的构造方法
vector<vector<int>> result(n,vector<int>(n,0));
int count=1;
int startx=0,starty=0;
int x=startx,y=starty;
int offset=1;
int loop=n/2;
while(loop--){
for(y=starty;y<n-offset;y++){
result[startx][y]=count++;
}
for(x=startx;x<n-offset;x++){
result[x][y]=count++;
}
for(;y>starty;y--){
result[x][y]=count++;
}
for(;x>startx;x--){
result[x][y]=count++;
}
//第一次循环结束后,这里x已经--了,等于0了
offset++;
startx++;
starty++;
}
if(n%2){
int middle=n/2;
//这里索引不能用表达式,要重新定义一个变量
result[middle][middle]=count++;
}
return result;
}
};