977.有序数组的平方
题目链接:
尝试解答:定义两个指针一个指向头(left),一个指向尾(right)。nums[left]和nums[fight]进行比较,较大数放入前端。然后做死了。
思路:
1.如何想到用双指针,对于题目中可能存在负数,整个数组平方后呈现两边大中间小,故想到两个指针同时向中间靠拢。
2.如何解决数组填充顺序问题:两头指向中间的过程中先指到较大的数,但题目要求从小到大排列,故令k = nums.size() - 1,反着填充数组。
3.for循环的弹出条件:i <= j而不是i < j, 若是后者则在i = j时这个数没有被装进去。
4.其实在尝试解答时完全是自己想多了,题目并没有要求原地更新数组,所以可以重新开辟一个vector,将元素按顺序向该vector里填充。这样这个题在思路上就没有什么难度了。
第一次代码写成了这样:出现了空指针异常的情况。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result; //没有说明result的内存。
int index = nums.size() - 1;
for(int i = 0, j = nums.size() - 1; i <= j; ){
if(nums[i] * nums[i] >= nums[j] * nums[j]){
result[index--] = nums[i] * nums[i];
i++;
}else{
result[index--] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
对比标准代码是在vector定义时出了问题。
改正后:(这种错误的原因是在栈和队列时习惯性的定义方式,在栈和队列的库函数内部会进行内存的分配,所以不会空指针异常,但在这道题这种情况需要提前分配够内存)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(), 0);
int index = nums.size() - 1;
for(int i = 0, j = nums.size() - 1; i <= j; ){
if(nums[i] * nums[i] >= nums[j] * nums[j]){
result[index--] = nums[i] * nums[i];
i++;
}else{
result[index--] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
209.长度最小的子数组(滑动窗口)
BF解法:两个for循环
双指针:一个for循环
思路:
滑动窗口:最重要的精髓——如何移动起始位置
起始位置何时移动?当终止位置移动到目前已遍历的数组元素和大于目标之后,起始位置开始移动、
关键点:for循环的索引一定指向的是滑动窗口的终止位置。
易错提醒:起始位置是一个持续的向后移动的过程,故应该用while循环移动起始位置,而是不if(如果是if则只移动一次,可能还不是最短的情况)
总结:
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
代码如下:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length = INT_MAX, sum = 0;
for(int last = 0, first = 0; last < nums.size(); last++){
sum += nums[last];
while(sum >= target){
length = min(length, last - first + 1);
sum -= nums[first];
first++;
}
}
return length == INT_MAX ? 0 : length;
}
};
自己写代码时出现了两处问题:
1.一开始在while循环里没有取 = 。起始sum == target时此时窗口已经满足条件了,故要将此时的窗口长度last - first + 1与之前的最短窗口length作比较。
2.不知道不存在满足题意的窗口的测试组怎样返回0,见上面答案。
59.螺旋矩阵(***语法上易错,逻辑细节容易理不清,值得多次复习***)
尝试解答:
问题:1.怎样定义新的vector<vector<int>> result ?
2.在向上向下转角处怎样装填数组?
重点:1.转圈时如何处理边界条件——遵循循环不变量原则,每一次循环都是同样的规则。本题都是左闭右开,最后一个点留给下一条边处理.
2.使用while循环
3.定义多少个变量,怎样定义变量,每一轮while循环变量做怎样的变化,才能实现一圈一圈走的逻辑。
4.如果边长是单数,存放最中间的数字的语法易错。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n, 0));
int start_x = 0, start_y = 0, offset = 1, count = 1;
int i = 0, j = 0, loop = n / 2; //分别定义i, j,分开指示行列
while(loop--){ //设置loop变量,判断循环次数
j = start_y;
i = start_x; //必须在此处就将i,j的值更新
for(; j < n - offset; j++){
result[i][j] = count++;
}
for(; i < n - offset; i++){
result[i][j] = count++;
}
for(j = n - offset; j > start_y; j--){
result[i][j] = count++;
}
for(i = n - offset; i > start_x; i--){
result[i][j] = count++;
}
offset++;
start_x++;
start_y++;
}
if(n % 2 == 1){ //判断是否存在中心数应该用模运算
int mid = n / 2;
result[mid][mid] = count;
}
return result;
}
};