目录
leetcode977.有序数组的平方
题目链接:977.有序数组的平方
思路
考虑到数组中存在负数,所以原数组元素平方后的最大值要么为最左端的最小负数平方后所得,要么为最右端的最大正数平方后所得。因此考虑用双指针去处理,从两端开始逐次比较平方后数的大小,将更大的平方数填入新数组并将指向该元素的指针向左或向右移动一位。
代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int i, j, n;
vector<int>result(nums.size() ,0 );
i = 0;
j = nums.size() - 1;
n = nums.size() - 1;
while(i <= j){
if(nums[i] * nums[i] >= nums[j] * nums[j]){
result[n--] = nums[i] * nums[i];
i++;
}
else{
result[n--] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
复杂度
时间复杂度:O(n) , 只针对原数组元素进行一次遍历比较
空间复杂度: O(1) , 给定有序数组
leetcode209.长度最小的子数组
思路
本题的暴力解法为双重循环遍历符合条件的最小子序列,第一层循环变量为子序列的左顶点,第二层循环变量为子序列的右顶点。遍历求出长度最小的子数组,该复杂度为O(n^2)。
对于本题我们还有另一种思路求解:滑动窗口
所谓滑动窗口即不断调整子序列的起始位置和终止位置,从而得出我们想要的结果。
如果想要使用滑动窗口解决本题,我们需要明确的有以下三点:
1.窗口的内部是什么?
窗口的内部即为我们要找寻判断的最小子序列。
2.如何移动窗口的起始位置?
当前窗口的总和大于target是之时,窗口就要缩小了,即移动起始位置。
3.如何移动窗口的终止位置?
终止位置的移动依靠终止位置作为一层for循环当中的索引。
for(j = 0; j < nums.size(); j++){ //窗口的终止位置
sum += nums[j];
//注意这里使用while,每次更新i(窗口的起始位置),不断的缩小窗口判断是否符合条件
while(sum >= target){
sublength = j - i +1;//窗口的长度即为子序列的长度
result = result < sublength ? result :sublength;
sum -= nums[i++]; //更新窗口值,缩小窗口
}
}
可以发现滑动窗口的神奇之处在于,根据当前子序列和其大小,不断移动窗口的起始位置,从而使得复杂度从暴力解法的 O(n^2)降为了O(n)。
代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i = 0;//窗口的起始位置
int j;
int sum = 0;//窗口内的数值之和
int result = INT32_MAX;
int sublength = 0;//窗口的长度
for(j = 0; j < nums.size(); j++){//移动窗口的终止位置
sum += nums[j];
while(sum >= target){
sublength = j - i +1;//更新窗口长度
result = result < sublength ? result :sublength;
sum -= nums[i++];//缩小窗口
}
}
//如果没有任何一段子序列符合条件,则返回0
return result == INT32_MAX ? 0:result;
}
};
复杂度
时间复杂度:O(n)
数组内的每个元素在进入窗口的时候操作了一次,退出窗口的时候操作了一次。一共是2n次。
空间复杂度: O(1) ,给定数组
leetcode59. 螺旋矩阵 II
题目链接:59.螺旋矩阵II
思路
螺旋矩阵的每圈有4条边,上边从左到右,右边从上到下,下边从右到左,左边从下到上。因此采用4个循环依次遍历每条边。一共需要画loop = n/2圈,因此用一个while(loop--)循环套住这4个遍的for循环。在for循环中需要注意的是每次遍历的边界,需要保持循环不变量,使得在同一圈当中,每条边的for循环遍历的个数一致,才能无差错的勾勒出该螺旋矩阵。同时需要注意每画一圈时,循环的右边界都会缩小一位。
代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int loop = n/2;
//若n为奇数,则矩阵中心点的坐标为(midx,midy)
int midx = n/2;
int midy = n/2;
vector<vector<int>> result( n , vector<int>(n , 0) );//定义一个二维数组
int count = 1;//用来给矩阵中的每一个位置赋值
int starx = 0, stary = 0;//每一次的循环的起始位置
int offset = 1;//控制每次循环的遍历长,每次循环右边界都会收缩一位
int i,j;
while(loop--){
i = starx;
j = stary;
// 填充上行从左到右
for(j = stary; j < n - offset; j++){
result[starx][j] = count++;
}
//填充右行,从上到下
for(i = starx ; i <n - offset; i++){
result[i][j] = count++;
}
//填充下行,从右到左
for(; j >stary ; j--){
result[i][j] = count++;
}
//填充左行,从下到上
for(; i > starx ; i--){
result[i][j] = count++;
}
//新的一圈开始,起始点的xy各自加1,例如第一圈起始点是(0,0),第二圈的起始点为(1,1)
starx++;
stary++;
//循环右边界缩小一位
offset++;
}
//当n为奇数是,螺旋矩阵的尾巴为该矩阵的中心点,此时while循环已经结束,需单独为该中心点赋值
if(n%2 == 1){
result[midx][midy] = count;
}
return result;
}
};
复杂度
时间复杂度:O(n^2) ,螺旋矩阵共有n^2个元素,每个位置在循环赋值的过程中操作一次。
空间复杂度:O(1) ,对于一个给定的n二维数组的大小为常量。