209长度最小的子数组
题目链接
题目描述
给定一个含有 n
个正整数的数组和一个正整数 target
。找出该数组中满足其总和大于等于 target
的长度最小的子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
代码思路
先进行排序,然后从数组末尾向前移动,将整数依次相加直至大于等于target,同时统计数量从而得出子数组长度。
运行结果显示解题错误,仔细看题目发现子数组不能改变序列顺序,想错了。
int minSubArrayLen(int target, vector<int>& nums) {
sort(nums.begin(),nums.end());
int addnum=0,time=0,len=nums.size()-1;
while(time<nums.size()){
addnum+=nums[len-time];
time++;
if(addnum>target||addnum==target){
return time;
}
}
return 0;
}
看知识星球后发现是两种方法,一种暴力破解,一种滑动窗口法,暴力破解就是两个for循环,滑动窗口相较于暴力破解从思想上主要在于在已经符合target的窗口内继续寻找下一个时不需要再重新相加至已知之前已知不足target的部分从而减少时间上的消耗,而在代码的体现主要就在于内循环的for改成了while,并且计算整数和时不需要清零。
错误原因
1、书写过程中发现在写for循环时还是不清楚滑动窗口这一概念,窗口起始和窗口末尾需要单独记录,for主要滑动的是窗口的末尾。
2、先是出现溢出,后发现是因为没有改变窗口前侧大小,导致溢出,但是这也没有多大的数字怎么会溢出呢?不太懂
3、发现结果都是0,因为将result直接先设置成了0,想说如果有哪个结果比result小取谁,没想到会导致结果直接就是0了,第一次明白为什么要先设置为INT32_MAX
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result=INT32_MAX;
int len=0;//滑动窗口长度
int sum=0;
int l=0;//滑动窗口前侧
for(int r=0;r<nums.size();r++){//注意这里的窗口右侧从左侧开始滑动
sum+=nums[r];
while(sum>=target){
len=(r-l+1);
result=result<len?result:len;
sum-=nums[l];
l++;
}
}
return result==INT32_MAX?0:result;
}
};
59螺旋矩阵||
题目链接
题目描述
给你一个正整数 n
,生成一个包含 1
到 所有元素,且元素按顺时针顺序螺旋排列的
正方形矩阵
matrix
。
代码思路
这道题可谓是没有思路,之前考试这道题就没做出来。看看知识星球吧,看完发现原来是这么拆解的,先确定循环次数,看每次循环中不同方向的相同之处,不同循环的相同之处,矩阵中间还有一个不参与循环之处。
错误原因
Char 34: runtime error: addition of unsigned offset to 0x502000000070 overflowed to 0x50200000006c,经过查询是数组元素访问越界,不知道哪里出错了,但是后来对比代码一堆不对的地方:
1、i和j在每一次循环时都需要更新循环起点的位置,要以多次循环为思考方式
2、在向左和向上循环时,for循环中使用了=,使得其最后回归原点,导致数据错误
3、中间位置需要单独设置仅当n为奇数时
4、因为loop循环次数是n/2,认为和中间位置的坐标值一致,后发现loop在循环时候被使用已经减为0了,所以得单独设置一个mid用来存储中间位置
5、循环起始位置变换的同时,每一次循环的长度边界值也需要变化
区间和
题目链接
58. 区间和(第九期模拟笔试) (kamacoder.com)
题目描述
给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
输入描述
第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间,直至文件结束。
输出描述
输出每个指定区间内元素的总和。
代码思路
这一代码没有进行书写,进行了文章阅读,首先看到这一题目确实第一想法是直接相加即可,而这道题目卡的就是直接相加的方法的时间消耗过大的问题,所以可以先直接进行子数组的计算,使得只需进行n次计算就可得到n各子数组,在进行区间计算的时候只需要一次计算就可得出,这和长度最小的子数组的滑动窗口有异曲同工之妙啊!另外,里面也提到如果涉及时间的话,C++使用scanf和printf比cin和cout更节省时间,下次可以试试。
总结
一共用了2h30min弄明白三道题,总的来说学习了滑动窗口的写法,以for...while...写法作为记忆,同时也学习了如何在顺时针螺旋循环中找规律的方法,没有想到这个还可以用到二分法中的左闭右开法则,其次,在区间和中学习了怎么通过同子数组计算从而简化重复计算,当然这些是总的方法,在明白了大致思维后,还有很多更为细致的细节,这在上方也进行了记录。