文章目录
前言
详细的包含main函数的代码,小白可直接在vs运行~
一、有序数组的平方977
文档&视频讲解:代码随想录
1. 题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
提示:非递减序列:前一个数 <= 后一个数
2. 思路
- 暴力解法:
for循环遍历数组,对每个元素平方;
用sort对数组快速排序。 - 双指针:
提示:因为是非递减序列,平方后的最大值必然在两端
数组两端取平方比较大小,大者放入 result [k] 最后一位;
k- -;i++ 或 j- -后 继续比较平方比较大小…
3. 代码实现
暴力解法
//Time:2024/4/17训练营跟练
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
vector<int> sortedSquared(vector<int>& nums) {
int size = nums.size();
for (int i = 0; i < size; i++) {
nums[i] = nums[i] * nums[i];
}
//排序
sort(nums.begin(), nums.end());
return nums;
}
};
int main()
{
vector<int> nums = { -4,-1,0,3,10 };
Solution solution;
vector<int> result = solution.sortedSquared(nums);
cout << "[";
//result是一个vector,经过for_each遍历之后成为vector里的每个int值
for_each(nums.begin(), nums.end(), [](int result) {cout << result << " "; });
cout << "]";
return 0;
}
双指针
//Time:2024/4/17
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
vector<int> sortedSquared(vector<int>& nums) {
//vector<int> result = { 0 };
//定义新数组大小和result一样大,且所有元素初始化为0
vector<int> result(nums.size(), 0);
int k = nums.size() - 1;
//注意循环条件:不是 i < nums.size(),而是i<=j
//for (int i = 0, int j = nums.size() - 1; i <= j ;)错误
//int类型定义重复
for (int i = 0, j = nums.size() - 1; i <= j ;) {
if (nums[i] * nums[i] >= nums[j] * nums[j]) {
result[k] = nums[i] * nums[i];
//别忘了两个数组的指针都要变化
k--;
i++;
}
else {
result[k] = nums[j] * nums[j];
k--;
j--;
}
}
return result;
}
};
int main()
{
vector<int> nums = { -7,-3,2,3,11 };
Solution solution;
vector<int> result = solution.sortedSquared(nums);
for_each(result.begin(), result.end(), [](int result) {cout << result << " "; });
return 0;
}
4.Debug与收获
暴力解法 2024/4/17 一刷
Debug:
- 遍历数组时,i<size 不是 i<size-1,(表示数组元素个数时-1)后续还有,代值进去看
收获:
- algorithm: sort & for_each
- lambda表达式
双指针 2024/4/17 一刷
Debug:
- for (int i = 0, int j = nums.size() - 1; i <= j ;)错误
两个参数的for循环,类型不要定义重复了- 两个数组,数组的指针都要变化;
i,j变化—>k也要变- 注意循环条件 不是 i < nums.size(),而是i<=j
收获:
- 定义新数组的方式:大小和result一样大,且所有元素初始化为0
// vector result(nums.size(), 0);
二、长度最小的有序数组209
文档&视频讲解:代码随想录
1. 题目
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示:
1 <= target <= 10^9
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
2. 思路
提示:
i、j共同构成一个滑动窗口,i、j是nums的索引;
result 是一个判断nums所有元素的和 是否能满足s 的条件;
i的移动条件是sum>=s
j是一直遍历整个数组
提示:INT_MAX 和 INT_MIN 是 C++ 的两个宏,代表了整型变量能够存储的最大正整数和最小负整数,分别为 2147483647 和 -2147483648,这两个宏在头文件 <limits.h> 中定义。
3. 代码实现
//Time:2024/4/17训练营跟练
//
// 变量说明:
// i:窗口起始位置
// j: 窗口结束位置---作为遍历整个数组的索引
// sum: 窗口内元素求和
// subLength: 窗口长度
// result:最终窗口长度
#include<iostream>
#include<vector>
#include<limits.h>
using namespace std;
class Solution {
public:
int minSubArrayLen(vector<int>& nums, int s) {
int size = nums.size();
int sum = 0;
int i = 0;
int result = INT32_MAX;
//int subLength = 0;
for (int j = 0; j < size; j++) {
sum += nums[j];
//更新subLength、result、i、sum
while (sum >= s) {
//subLength = j - i + 1;
int subLength = (j - i + 1);
result = result > subLength ? subLength : result;
//sum -= nums[i++];//后置++,先对表达式 +,再对变量 +
sum = sum - nums[i];
i++;
}
}
return result = result == INT32_MAX ? 0 : result;
}
};
int main()
{
vector<int> nums = { 1,4,4 };
int s = 4;
Solution solution;
int len = solution.minSubArrayLen(nums, s);
cout << len << endl;
return 0;
}
4. Debug与收获
双指针
2024/4/18一刷
Debug:
subLength = j - i + 1 ×
subLength = (j - i + 1) √sum -= nums[i++]; 后置++的含义,先用原来的i带入运算,再对i++
(后面一题将会对后置++有更深刻的理解)收获:
while:只要条件满足,就一直执行循环语句
if:条件满足,执行循环语句,然后就跳出来了
三、螺旋矩阵59
文档&视频讲解:代码随想录
1. 题目
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
2. 思路
- 循环不变量原则,全部左闭右开
- 先按n为偶数来转圈,最后补充n为奇数时不成圈的最中间元素
- 循环中判断i、j是否不变,变的范围,怎么变,循环就很好写
- 一圈中,起始位置是不变的,就像拴狗绳钉在那,然后狗绕圈
- 一圈结束,开始第二圈前,改变起始位置(startx&starty);同时,循环的范围(n-offset)也要变,两端同时向内收缩,第二圈的雏形就出来了
- 注意:count++是先用原始值进行表达式运算,再改变自身,故第一个cout++是count=1,后一个才是赋的coun++:2
- 故最后奇数的赋值count++和count均可
提示:注意:count++是先用原始值进行表达式运算,再改变自身,故第一个cout++是count=1,后一个才是赋的coun++:2
故最后奇数的赋值count++和count均可
3. 代码实现
//Time:2024/4/18训练营跟练
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//形参用引用,这里不是形参
vector<vector<int>> res(n, vector<int>(n, 0));
int startx = 0, starty = 0;//定义起始位置的横纵坐标
int i, j;//定义变化的索引
int offset = 1;//辅助n,保证左闭右开
int count = 1;//赋值
int loop = n / 2;
int middle = n / 2;
//先不管n为奇或偶,先循环整圈
while (loop--) {
i = startx;// 此时startx和starty均为0,不变;变化的是i、j
j = starty;
//开始循环
//第一行,i不变,j++
for (j; j < n - offset; j++) {
//这里cout++是因为赋给的是count=1,后一个才是赋的coun++:2
res[startx][j] = count++;
//不行,因为第二圈startx会++
//res[i][j] = count++;
}
//最后一列,j不变,i++
for (i; i < n - offset; i++) {
res[i][j] = count++;
}
//最后一行,i不变,j--
//要用startx作为循环变量,为后续第二圈循环做准备
for (j; j > startx; j--) {
res[i][j] = count++;
}
//第一列,j不变,i--
for (i; i > starty; i--) {
res[i][j] = count++;
}
startx++;
starty++;
offset++;
//上述两组自增,使圈两边都缩小了,可以开始第二圈循环
}
//若n为奇数,单独为中间不成全的值赋值
// ?
//count++是先用表达式赋值,再变量加
if (n % 2) {
res[middle][middle] = count++;
}
return res;
}
};
int main() {
int n = 3;
Solution solution;
vector<vector<int>> result = solution.generateMatrix(n);
//用for循环输出数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::cout << result[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
4. Debug与收获
2024/4/18一刷
收获:
- 二维数组的写法
总结
- 还好昨天提前写了一题,要不然今天就完不成任务了
- 今天看到一篇双非本科上岸的帖子,被激励了,但我确实还有很大差距
- 但每天都在进步不是吗?(写思路的时候发现进步好大。。。可能是被后两题折磨出来的
- 成长的秘诀可能就是常常少一点放纵吧
- 这样写心情总结好羞耻。。。但还挺有意思的
- 今天画了一个导图,确实有助于整理思路
- 今天写博客时间明显短了很多,果然完事开头难
还需复习:
8. 27. 移除元素 暴力解法
9. for_each输出、 lambda 表达式
10. 今天的后两题明天要二刷一下
10.时间复杂度怎么计算。。。