第一题.209. 长度最小的子数组 - 力扣(LeetCode)
最开始做这道题的时候没有仔细审题....,没看到是子序列,然后先对数组排序然后动态规划做了....简单问题复杂化了。。下次要好好读题呜呜呜😭并且题干要求不是正好等于target,题干说的是大于等于target。
思路A:暴力枚举。长度j-i+1(不要总因为加不加1的问题,而一直纠结。。。),然后当时做的时候res的初始值随便🫤设置的,,导师后面返回的时候出现了错误。。。。(我真是无语死了。。。)---》超时
int minSubArrayLen(int target, vector<int> &nums) // 注意审题,这道题要找最短序列!
{
int res = INT32_MAX; // 最终结果
int sum = 0, len = 0; // 子序列的和,子序列长度
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; // 更新长度
res = res < len ? res : len;
break;
}
}
}
return res == INT32_MAX ? 0 : res;
}
思路B:滑动窗口
简而言之,就是不断调节子序列的起始位置和终止位置,从而得到我们想要的结果。
比如 2 3 1 2 4 3【7】 --》2 3 1 2 4 3--》2 3 1 2 4 3--》2 3 1 2 4 3--》2 3 1 2 4 3--》
2 3 1 2 4 3--》 2 3 1 2 4 3--》2 3 1 2 4 3
int minSubArrayLen(int target, vector<int> &nums) // 注意审题,这道题要找最短序列!
{
int res = INT_MAX;
int sum = 0, len = 0;
int low = 0; // 滑动窗口起始位置
for (int high = 0; high < nums.size(); high++)
{
sum += nums[high];
while(sum >= target)//注意这里是while,不是if。因为高低指针都要不断的变更!!
{
len = high - low + 1;//取子序列长度
res = res < len ? res : len;
sum -= nums[low++];//体现出滑动窗口的精髓!!不断变更low(子序列起始位置)
}
}
return res == INT_MAX ? 0 : res;
}
注意⚠️,时间复杂度是O(n),因为主要是看每个元素被操作的次数。每个元素进去一次出去一次,O(2n)。
第二题:59. 螺旋矩阵 II - 力扣(LeetCode)
一入循环深似海,秋招offer say byebye~~~
思路:第一要注意点是边界处理问题!!全程保持一致:左闭右开
第二是循环次数的问题 n/2
第三是那几个变量赋值问题(我最开始这里完全搞混了,offset也没有引入,然后全程写的代码像💩一样冗余。然后循环之后变量更新,startx和starty++,这里误写成了i和j,我可真逆天😅)
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>> res(n, vector<int>(n, 0));
int loop = n / 2; // 表示转的圈数,因为转一圈减2,2x=n.
int startx = 0, starty = 0; // 表示每一圈的起始位置
int offset = 1; // 表示每一圈的偏移量
int count = 1;
int i = 0, j = 0;
while (loop--) // 循环的时候要保持左闭右开!
{
i = startx;
j = starty;
for (j; j < n - offset; j++)
{
res[i][j] = count++;
}
for (i; i < n - offset; i++)
{
res[i][j] = count++;
}
for (j; j > starty; j--)
{
res[i][j] = count++;
}
for (i; i > startx; i--)
{
res[i][j] = count++;
}
startx++; // 每转完一圈,初始值加1.
starty++;
offset++;
}
if (n % 2 == 1)
res[n/2][n/2] = count; // 当n为奇数的时候,会剩下一个中间的数,需要单独赋值。
return res;
}
第三题 区间和 问题---前缀和
题目描述:给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
比如1 2 3 4 5。求下标0和1区间元素。或者求下标1和3之间的元素。
思路1:暴力求解
for(int i = a;i<=b;i++) sum+=vec[i];
思路2:区间和求解方法
p[1] = vec[0]+vec[1]; p[3] =vec[0] + vec[1] + vec[2] + vec[3];
p[3]-p[1] = vec[2]+vec[3]。我们发现少一个数字vec[1],所以如果要求[1,3]之间的区间和,应该是p[3]-p[0];
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for (int i = 0; i < n; i++) {
cin >> vec[i]; //scanf("%d",&vec[i]);
presum += vec[i];
p[i] = presum;
}
while (cin >> a >> b) { //while(~scanf("%d%d",&a,&b)){
//这里注意scanf的返回值是读入元素的个数。
int sum;
if (a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
cout << sum << endl; //printf("%d/n",sum);
}
}
注⚠️:C++面对大量数据的时候,最好用scanf和printf,耗时会小很多。如上所示。