代码随想录阅读总结:长度最小的子数组

长度最小的子数组

题目链接

思路

看到这道题我其实懵的一下,以为这个字串不连续。

仔细读题后,才发现是连续,这个条件让暴力变得非常直观,且简单

暴力法直接两个循环,类似冒泡一样,每次外循环记录一次子数组长度。

如果这次外循环的数组之和大于等于val值,则进行一次长度值的比较,这个值小于之前存的最小长度则更新,不小于不更新。很直观是吧,但还是有点low

让我们换个思路,想一想,这个目标最小长度值的数组是连续的。我们从数组的第一个值开始考虑,这个值单独的和不够大,只有一条路可走,那就是加上它的下一个值。因为目标数组是连续的嘛。加上下一个不够就就再加,直到恰好等于或者大于。

等于的时候,说明这个满足等于条件,但不一定最小,所以要把它和存的最小值比较(初试最小值默认非常大),小于最小值则更新,和暴力差不多对吧。当然也别忘了继续减去子数组的第一个数,我们还要继续找,不是吗?当然,加上子数组的下一个数也是一样的,可以自己推理一下。

大于的时候,我们不能再往回退了对吧,那样就重了。我们只能去掉第一个数,因为是连续的嘛,单独去掉第二个就不连续了。而且再加上一个数的长度就一定不是最小的了,所以虽然再加上下一个值满足条件,但一定不是最小的,所以之后的都不要了。有意思吧,就像个窗口一样,向右滑动。

小于就加上数组的下一个数,大于就减去数组的前一个数,这样的搜索法是不是很高级,哈哈哈。

暴力法

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX;
        for(int i=0;i<nums.size();i++){
            int sum=0;
            for(int j=i;j<nums.size();j++){
                sum+=nums[j];
                int sublength = j-i+1;
                if(sum>=s){
                    result = result < sublength ? result : sublength;
                    break;//因为这个满足条件,其后一定满足但都不是目标值。所以进行下一次的外循环。
                }
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

这个代码仅能通过测试,提交时会超时,但结果没有问题。换句话说,效率太low了。

滑动窗口法

代码如下:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX;//INT32_MAX是一个很大的数,多大我也不清楚,反正就是目前够你用的大。
        int sum = 0; //窗口数值之和,由于全局参与且每次都可能更新,所以在所有循环外定义。
        int i = 0; //这个用于指向起始位置
        //问我为什么j是定义在循环里的,因为j一定会到大原数组末尾,但i不一定,i类似一个慢指针。
        int subLength = 0;//用于记录每次的长度,并于result进行比较
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            while (sum >= s) {
                subLength = (j - i + 1);//提取数组长度,小学的逻辑题,别告诉我你不懂。
                result = result < subLength ? result : subLength;//正确:左边,错误取:右边。注意符号是英文的。
                sum -= nums[i++];//i++和++i分别是语句执行完后加1和执行之前加1,当然,我指的是本行语句。
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值