3道题目
有序数组的平方977
长度最小的子数组209
螺旋矩阵59
解题理解
977
题目给出数组非递减,但存在负数的情况,容易想到单指针遍历然后排序的方法,但可以尝试使用双指针优化复杂度。
多列举出几种情况,当不存在负数,则最大数在数组右侧,若存在负数,则最大数也可能出现在左侧,而最小数不太好确定位置,所以这道题从最大值即新数组的最右侧开始排序更合适。
可以设计头尾双指针,通过从这两个最有可能出现最大数的端点开始比较,更大的放进新数组最右侧,头尾指针的数哪个被放进新数组,哪个向内收缩。
209
题目明确只需要给出最小子数组长度,不需要给出最小子数组,所以可以通过单次遍历得出,但是最小子数组无法保证是否是从第0位开始的。
所以依然采用双指针的思路,两指针初始化在数组首位,fast不断叠加扫过的值。当第一次大于target时,需要将slow提上来,然后再算一遍fast和slow之间的和(这一步不需要遍历,因为从fast扫过的叠加和可以保存之后再减去slow),如果还是比target大,slow还需要往前提,这里提slow的过程是为了确保子数组是最小的,最小子数组在这个过程里完成不断地更新。
59
题目本身并没有明显的算法要求,只是要将矩阵转圈的过程模拟出来。这个过程中关于端点处的边界条件很容易模糊,越写越绕,可以借鉴昨天左闭右开的思路。
对于每圈的端点都采用“开”的操作,就是要将每条边的最后一个元素放到下一条边的开始去处理。多列举几种情况可以发现,绕圈数=n/2,n取奇数时,最中心元素可以最后直接将n*n放进去。
//59. 螺旋矩阵 II
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int startx = 0,starty = 0;
int i = 0, j = 0;
int offset = 1, count = 1;
int circle = n / 2;
int c = 0;
vector<vector<int>> res(n, vector<int>(n, 0));
while(c < circle){
for(i = startx, j = starty; j < n - offset; j ++){
res[i][j] = count ++;
}
for(i = startx; i < n - offset; i ++){
res[i][j] = count ++;
}
for(;j > starty; j --){
res[i][j] = count ++;
}
for(;i > startx; i --){
res[i][j] = count++;
}
startx ++;
starty ++;
offset ++;
c ++;
}
if(n % 2 == 1) res[circle][circle] = n * n;
return res;
}
};
本体思路还是比较容易想到的,但是在实现的过程中发现对于左闭右开这一循环中不能变的特性没有很好的思路,看了代码之后发现只需要一个offset参与进循环就好。看来还是对于双指针的运用不够熟练,还需要其他题的练习。