代码随想录算法训练营第二天 | 209长度最小的子数组 ,59螺旋矩阵||,区间和

209长度最小的子数组

题目链接

209. 长度最小的子数组 - 力扣(LeetCode)

题目描述

给定一个含有 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螺旋矩阵||

题目链接

59. 螺旋矩阵 II - 力扣(LeetCode)

题目描述

给你一个正整数 n ,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n\times n正方形矩阵 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...写法作为记忆,同时也学习了如何在顺时针螺旋循环中找规律的方法,没有想到这个还可以用到二分法中的左闭右开法则,其次,在区间和中学习了怎么通过同子数组计算从而简化重复计算,当然这些是总的方法,在明白了大致思维后,还有很多更为细致的细节,这在上方也进行了记录。

  • 19
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喝西北风吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值