代码随想录day2的数组题目
文章参考的代码随想录的网址:代码随想录的数组章节的参考地址
977.有序数组的平方:
刚看题的思路 :
暴力解决,先平方出来,然后用sort函数来排序,但这种算法的时间复杂度为 O(n + nlogn)
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
for (int i = 0; i < A.size(); i++) { //遍历容器A的元素
A[i] *= A[i];
}
sort(A.begin(), A.end()); // 快速排序
return A;
}
};
正确思路:
双指针法:数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间;
定义 i 指向起始位置,j 指向终止位置;定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
int k = A.size() - 1;
vector<int> result(A.size(), 0);
for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
if (A[i] * A[i] < A[j] * A[j]) {
result[k--] = A[j] * A[j];
j--;
}
else {
result[k--] = A[i] * A[i];
i++;
}
}
return result;
}
};
209.长度最小的子数组:
刚看题的思路
使用两个for循环,第一层的for循环,不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
sum = 0;
for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
sum += nums[j];
if (sum >= s) { // 一旦发现子序列和超过了s,更新result
subLength = j - i + 1; // 取子序列的长度
result = result < subLength ? result : subLength;
break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
正确思路
滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果;
只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置;
重点:滑动窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引
理解点:滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置
59.螺旋矩阵II:
刚看题的思路
无思路
正确思路
求解本题依然是要坚持循环不变量原则。
模拟顺时针画矩阵的过程:
填充上行从左到右
填充右列从上到下
填充下行从右到左
填充左列从下到上
由外向内一圈一圈这么画下去
// 坚持循环不变量原则 左闭右开
class Solution {
public:
vector<vector<int>> generateMatrix(int n) { // 二维容器 n行,列数不固定
vector< vector<int> > res(n, vector<int>(n,0)); // 使用一个vector去定义一个二维数组
int startx = 0 , starty = 0; // 定义每循环一个圈的起始位置
int loop = n /2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int mid = n /2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
int count = 1;
int offset = 1;
int i ,j;
while(loop--){
i = startx;
j = starty;
// 下面开始的四个for就是模拟转了一圈
// 模拟填充上行从左到右(左闭右开)
for(j; j< n -offset; j++ ){
res[i][j] = count++;
}
// 模拟填充右列从上到下(左闭右开)
for(i; i< n -offset; i++ ){
res[i][j] = count++;
}
// 模拟填充下行从右到左(左闭右开)
for(; j > starty; j-- ){
res[i][j] = count++;
}
// 模拟填充左列从下到上(左闭右开)
for(; i > startx; i-- ){
res[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 1;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if(n % 2){
res[mid][mid] = count;
}
return res;
}
};