977 有序数组的平方
题目
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序
示例:输入:nums = [-4,-1,0,3,10],输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
思考
刚看到这题时发现只要将原数组所有元素平方后再排序就完事了,但要求是用双指针来解答,思考良久,核心点在于不明白双指针不仅可以从同一起点出发,也可以从数组的前后两端向中间进行遍历,这题就是很好的例子,本题需要注意的有三点:
1、本题不存在快慢指针,只有左右指针,右指针的初始值在数组尾部
2、本题while循环的条件是left<=right,如果没有等于的话会少最后的结果会少遍历一个数
3、本题需要创建一个vector来存放结果,当得到结果时用 vector[pos] = 结果 的方式来存放,pos的位置可以从0也可以从vector尾部开始
代码
class Solution {
public:
vector<int> sortedSquares(vector<int> &nums)
{
vector<int> res(nums.size());
int left = 0, right = nums.size() - 1, pos = nums.size() - 1;
while (left <= right) {
if (abs(nums[left]) > abs(nums[right]))
res[pos--] = pow(nums[left++], 2);
else
res[pos--] = pow(nums[right--], 2);
}
return res;
}
};
209 长度最小的子数组
题目
给定一个含有 n
个正整数的数组和一个正整数 target
。找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例:
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组[4,3]是该条件下的长度最小的子数组
思考
本题有暴力和滑窗两种解法,我个人更倾向于滑窗法,其实滑窗和双指针很类似,同样都是用两个指针来进行遍历,区别是双指针在得到结果时是某一个数,而滑窗是左右指针截取的一段数组,滑窗法的基本步骤如下:
1、确定快慢指针:和双指针类似,一般都从数组头部或者一头一尾开始遍历
2、确定while循环条件:一般是right < nums.size()
3、根据题目要求来进行相应的计算处理,本题逻辑是当累加的和sum >= target时,对左指针进行右移操作,目的是找到最小长度的子数组
代码
// 滑窗法
class Solution {
public:
int minSubArrayLen(int target, vector<int> &nums)
{
// right是终止位置,res必须要设成int型最大值,因为刚开始要判断他是否大于sublength
int left = 0, right = 0, sum = 0, sublength = 0, res = INT_MAX;
while (right < nums.size()) {
sum += nums[right];
// 这里用while很关键,目的是在找到对应target的数组后再进一步看看有没有更小数组
while (sum >= target) {
sublength = right - left + 1;
res = min(res, sublength);
sum -= nums[left++];
}
right++;
}
// 这里的目的是搜索完整个nums没有找到对应的数组后返回0
return res == INT_MAX ? 0 : res;
}
};
// 暴力
class Solution {
public:
int minSubArrayLen(int target, vector<int> &nums)
{
int sum = 0, sublength = 0, res = INT_MAX;
for (int i = 0; i < nums.size(); i++) {
sum = 0;
for (int j = i; j < nums.size(); j++) {
sum += nums[j];
if (sum >= target) {
sublength = j - i + 1;
res = min(res, sublength);
break;
}
}
}
return res == INT_MAX ? 0 : res;
}
};
59 螺旋矩阵||
题目
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
思考
初看题目时完全懵,感觉无从下手,只看出来左上、右下和中间的数是啥,后面看了讲解视频才明白具体逻辑,其实就是按照示例1中的方向遍历矩阵的四条边,最外一圈遍历完了再向内一层遍历,需要注意的有两点:
1、每一条边的遍历都是左闭右开,最后一个数(也是下一条边的第一个数)放到下一条边去遍历
2、while循环(即转圈)的次数是n/2:n的平方(所有的数)除以4(四条边)再开方(一层层向内循环)
3、当n是奇数时,最中间也就是数组的最后一个数需要单独填充
代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>> res(n, vector<int>(n, 0)); // res要先赋值,不然会nullptr
// offset很关键,代表遍历的每一条边有offset个数放到下一条边去遍历,一般都是最后一个数
int startx = 0, starty = 0, offset = 1, count = 1;
int r = 0;
int i, j; // i,j要先声明,不然第十一行res[i][j]会找不到j是什么
while (r < n / 2) {
for (j = starty; j < n - offset; j++)
res[startx][j] = count++; // 上边
for (i = startx; i < n - offset; i++)
res[i][j] = count++; // 右边
for (; j > starty; j--)
res[i][j] = count++; // 下边,此循环刚开始时j = n-offset, i = n - offset
for (; i > startx; i--)
res[i][j] = count++; // 左边,此循环开始时i等于n-offset,j = 0
startx++;
starty++;
offset++;
r++;
}
if (n % 2 == 1)
res[startx][starty] = count; // 这里是在最中间位置存放数组最后一个数,也可以用res[n/2][n/2]来代替
return res;
}
};