有序数组的平方 leetcode977
暴力解法 时间复杂度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;
}
};
双指针解法 时间复杂度O(n)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(),0);
int k=nums.size()-1;
for(int i=0,j=nums.size()-1;i<=j;){
if(nums[i]*nums[i]>=nums[j]*nums[j]){
result[k--]=nums[i]*nums[i];
i++;
}else{
result[k--]=nums[j]*nums[j];
j--;
}
}
return result;
}
};
出现的错误
result[(nums.size()--)-1],一开始我是这样写的,编译出错,因为“--”操作符用于对变量自减操作,不能直接对一个表达式自减。
总结
学到了vector容器定义和初始化使用方法:
vector<int> vec; //创建一个空的整数向量
vector<int> vec(5); //创建一个包含 5 个初始化为 0 的整数的向量
vector<int> vec(5,10); // 创建一个包含 5 个初始化为 10 的整数的向量
长度最小的子数组 leetcode209
暴力解法 O(n^2) (会超时)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result=INT32_MAX;
int sum=0;
int len=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){
len=j-i+1;
result=result<len?result:len;
break;
}
}
}
return result==INT32_MAX?0:result;
}
};
其中INT32_MAX是32位有符号整型能表示的最大正整数,len用于记录子序列的长度,i为子数组的起点,j为子数组的终点。
出现的错误
1.第一个for循环之后没有重置sum=0。
2.第二个for循环中if语句中没有break,因为只要第一次满足sum>=target条件就一定是以当前i开头的最小子数组了,不用继续让j++,直接break跳出j的for循环,开始下一层i的for循环。
双指针移动窗口解法 O(n)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result=INT32_MAX;
int len=0,sum=0,i=0;
for(int j=0;j<nums.size();j++){
sum+=nums[j];
while(sum>=target){
len=j-i+1;
result=result<len?result:len;
sum-=nums[i++];
}
}
return result==INT32_MAX?0:result;
}
};
其中j为窗口的终点,i为窗口的起点,for循环遍历终点,只要满足sum>=target,此时就是以j为窗口终点满足条件的子数组,然后通过while循环中sum-=nums[i++],更改窗口起点位置直到不满足条件,此时更新的len就是以j为窗口终点满足条件的最小子数组,然后j++继续遍历。与暴力求解相比,这样通过实时改变子数组起点的方法可以减少一层for循环。
其中为什么要使用while循环判断而不是if语句呢?因为当固定起点遍历终点,达到sum>=target时,不一定是满足条件的最小窗口,例如:[1,1,1,1,100],target=100。
螺旋矩阵Ⅱ leetcode59
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n,vector<int>(n,0));
int startX=0,startY=0; //每一圈的起点
int loop=n/2; //转几圈
int count=1;
int offset=1;
int i,j;
while(loop--){
i=startX;
j=startY;
for(j;j<n-offset;j++){
result[i][j]=count++;
}
for(i;i<n-offset;i++){
result[i][j]=count++;
}
for(;j>startY;j--){
result[i][j]=count++;
}
for(;i>startX;i--){
result[i][j]=count++;
}
startX++;
startY++;
offset++;
}
if(n%2==1){
result[n/2][n/2]=n*n;
}
return result;
}
};
出现的错误
while (loop--) {
for (j= startY; j < n - offset; j++) {
result[i][j] = count++;
}
for (i= startX; i < n - offset; i++) {
result[i][j] = count++;
}
for (; j > startY; j--) {
result[i][j] = count++;
}
for (; i > startX; i--) {
result[i][j] = count++;
}
startX++;
startY++;
offset++;
if(n%2==1){
result[n/2][n/2]=n*n;
}
}
1.一开始我是这样写while循环的,这样写会导致进入第一个for循环之后因为i没有被初始化所以导致出错。
2.把判断n是奇数的if语句放在了while循环里面,导致当n=1时,进入不了while循环,给出的结果是[[0]],但其实应该是[[1]]。
总结
在使用for循环遍历每条边时最重要的是遵循循环不变量,也就是每条边左闭右开的原则。学到了使用vector定义二维向量的方法:vector<vector<int>> vec(n,vector<int>(m,0)),定义一个存放二维向量n行m列的容器且每个元素都初始化为0。