文章目录
目录
一、977.有序数组的平方
1.几个注意点
- 当然可以用暴力算法,先把每个数都平方以下,然后再排个序。时间复杂度为O(n + nlogn)。
- 优化一下,使用双指针法。核心:虽然说原数组存在负数,负数平方后可能会比正数的平方大,但是数组平方的最大值只能在数组两端,不可能是中间部分。因此,可以定义一个新数组(长度等于原来数组),从这个新数组的末尾进行存放,每次存放进去最大值。
2.代码实现
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;
}
};
二、209.长度最小的子数组
1.几个注意点
- 可以用暴力算法实现,两个for循环,枚举出所有可能性,时间复杂度O(n^2)。
- 滑动窗口思想,用一个for循环即可。核心:for循环中的变量j用来控制窗口的末尾(即终止位置),当滑动窗口所圈住的子数组符合题目条件时,便开始缩短窗口起始位置。时间复杂度为O(n)。
2.代码实现(滑动窗口思想)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;//result要设置成比原数组长度大,这样才能不断更新result
int i = 0;
int sum = 0;//记录目前滑动窗口中的各个元素之和
int len;//记录子数组长度
for(int j = 0;j < nums.size();j++){
sum += nums[j];
while(sum >= target){//只要sum大于target,就开始缩短窗口
len = j - i + 1;//len为目前符合条件的子数组的长度
result = len < result ? len : result;//更新result
sum -= nums[i];
i++;//缩短窗口(将窗口左端右移)
}
}
return result < INT32_MAX ? result:0;
}
};
3.代码实现(暴力算法)
看看就好,LeetCode中会超时。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int sum = 0;
int len;
for(int i = 0;i < nums.size();i++){
sum = 0;//每次循环前,先将sum置零
for(int j = i;j < nums.size();j++){
sum += nums[j];
if(sum >= target){
len = j - i + 1;
result = len < result ? len : result;
break;//一旦找到,就退出本轮循环,因为是求最小的子数组
}
}
}
return result < INT_MAX ? result : 0;
}
};
三、59.螺旋矩阵||
1.思想
- 输入一个数n,形成一个n*n的矩阵(n*n的数组),从最外面一圈开始,一圈一圈的不断赋值。
- 那就需要知道一共有几圈:n/2。如果n是奇数,只需最后额外单独将最中心的那一个点赋值。
- 圈数知道了,现在就该讨论每一圈如何赋值:分成四条边,每一条边用一个for循环赋值,注意这里的四条边,每条边的起始位置都是不同的,所以这边定义两个变量startx,starty来标记四条边赋值的起始位置。
- 注意循环不变量,即每次对“边”赋值的时候,遵循同一个规定:我这里遵循每条边的第一个点至倒数第二个点赋值。这样每次对四条“边”赋值的时候,都是遵循着这种规定。
- 注意每一圈过后,要改变初始位置和偏移量offset。
2.代码实现
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> nums(n,vector<int>(n,0));//定义一个二维数组
int startx = 0,starty =0;//startx记录初始行下标,starty记录初始列下标
int loop = n / 2;//记录一共有几圈
int offset = 1;//偏移量,每循环一圈之后,终止位置都要往左偏移一个
int i,j;
int count = 1;//记录对每条边每个点赋值的数据
while(loop--){//每一圈对四条边赋值
for(j = starty;j < n - offset;j++){
nums[startx][j] = count++;
}
for(i = startx;i < n - offset;i++){
nums[i][j] = count++;
}
for(;j > starty;j--){//此时j已经为正确的初始值,无需再赋值
nums[i][j] = count++;
}
for(;i > startx;i--){//此时i已经为正确的初始值,无需再赋值
nums[i][j] = count++;
}
//这一圈结束后,进行下一圈赋值时,需要改变初始位置
startx++;
starty++;
offset++;//偏移量也需要+1
}
//如果输入的为奇数,那么还需对中心点赋一次值
if(n % 2 == 1){
int middle = n / 2;
nums[middle][middle] = count;
}
return nums;
}
};