算法训练day2
209.长度最小的子数组: 给定一个含有n
个正整数的数组和一个正整数target
。找出该数组中满足其总和大于等于target
的长度最小的子数组[nums_l, nums_{l+1}, ..., nums_{r-1}, nums_r]
,并返回其长度。如果不存在符合条件的子数组,返回0
。
(1)暴力求解法:利用两个循环,分别遍历子列的起始位置和终止位置;若检查到和>= target
的子列,将其长度记为len;实时更新满足条件的最短子列长s。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0, len = 0, s = nums.size()+10;
for (int i = 0; i < nums.size(); i++){
sum = 0;
for (int j = i; j <nums.size(); j++){
sum += nums[j];
if (sum >= target) {
len = j-i+1;
break;
}
else len = nums.size()+10;
}
if (s > len) s = len;
}
return s == nums.size() + 10 ? 0 : s;
}
};
时间复杂度:O(n^2)
,这导致当n
很大时超出时间限制;
空间复杂度:O(1)
。
(2)移动窗口解法:利用一个for循环遍历窗口终止位置,以其和sum
是否大于target
作为元素是否在窗口中的依据。若sum
小于target
,向后移动窗口终止位置;若sum
大于target
,向后移动窗口起始位置。注意移动时和sum
的变化;并实时记录和比较子列长度。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0, sublenth = 0, result = INT32_MAX;
int i = 0; //star index
for (int j = 0; j < nums.size(); j++){
sum += nums[j];
while(sum >= target){
sublenth = j - i + 1;
result = result < sublenth ? result : sublenth;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i
continue;
}
}
return result == INT32_MAX ? 0 : result;
}
};
空间复杂度:O(n)
;
时间复杂度:O(1)
。
(3)解题困难:①不能准确判断移动窗口的起始位置i和终止位置j的设置;②尝试先固定子数组长度,再找满足和条件的子数组,最终还是要用两个循环。
59.螺旋矩阵: 给你一个正整数n
,生成一个包含1
到n^2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
(1)自我思路:n
为奇数时有中心,为偶数时只有外圈;一圈四边,每边的元素数目只计算左闭右开区间内的元素。
(2)循环求解:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
std::vector<std::vector<int>> arr(n, std::vector<int>(n,0));
int loop = n / 2; //记录要填充圈数,n为奇数时还需要单独处理中间位置
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
int mid = n/2;//记录中间位置
int offset = 1;
int count = 1;
int i, j;
while (loop--){
i = startx; j = starty;
for (j; j < n - offset; j++){ //j从0变到n-offset,n-offset未进入循环
arr[i][j] = count++;
}
for (i; i < n - offset; i++) {//j从0变到n-1
arr[i][j] = count++;
}
for (; j > startx; j--){ //j从n-offset 变到startx
rr[i][j] = count++;
}
for (; i > starty; i--){ //i从n-offset 变到starty
arr[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 1;
}
if (n % 2) arr[mid][mid] = n*n;
return arr;
}
};
时间复杂度:O(n^2)
;
空间复杂度:O(1)
。
(3)主要困难:误用行列乘积给元素赋值;区间端点i与j的设置;
(4)收获:自增运算符有共同效果和细微区别。① 后缀自增:i++ 会先返回 i 的当前值,然后 i 的值增加1。② 前缀自增:++i 会先将 i 的值增加1,然后返回 i 的新值。例如
int i = 1;
int a = i++; // a = 1, i = 2
int b = ++i; // i = 3, b = 3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端