Leetcode 209. 长度最小的子数组(小白学习之路)

题目描述:

这个题目一开始我没有看清题目中要求是“连续”的子数组,因此最早想到的方法是讲整个数组排序,如果最大的数满足>=s,则输出1,最大加第二大的数满足,则输出2.遇到这个测试用例时报错

s = 213, [12,28,83,4,25,26,25,2,25,25,25,12]

明确题意后,首先想到的方法是1.暴力法,两个指针,遍历几乎所有情况,代码如下:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) { 
        int slow=0,fast=0, minlen=10000,templen=255;    //一个慢指针一个快指针
        for(;slow<nums.size();slow++)     //慢指针从0开始
        {
            int sum=0;    //每开始一个慢指针,重置当前的和为0
            for(fast=slow;fast<nums.size();fast++)    //快指针从慢指针开始往后加
            {
                sum+=nums[fast];
                if(sum>=s)    //满足要求
                {
                    templen = fast- slow + 1;    //当前长度计算
                    if(templen<minlen) minlen=templen;     //如果小于最小长度,更新。这两行可以用一行min函数的代码搞定
                }
            }
        }
        if(templen==255) return 0;    //没有满足要求的情况,返回
        else return minlen;    

    }
};

看了下官方题解说的暴力法,时间复杂度有O(n3),我这种暴力法应该属于改良过的,时间复杂度应该只有O(n2),测试结果从执行用时上看很惨淡,说明肯定有更好的方法;

第二种方法2.滑动窗口法

这种方法算法课上老师有提到过,这次终于碰到实战应用,写了一下确实很快,总的来说就是一前一后双指针,形成了一个方框,所有的数加起来后如果<s,说明不存在满足要求的数组,返回0;如果总和>=s,则加左指针可使总和减小,在此期间探到最小的数组长度,代码如下:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int left = 0, right = 0, sum = 0, minlen = 10000;
        while (left < nums.size()&& right<nums.size())
        {
            if (sum >= s)     //总和大于S的情况,左指针右移
            {
                minlen = min(minlen, right - left);
                sum -= nums[left];
                left++;
            }
            else    //总和小鱼S的情况,右指针右移
            {
                sum += nums[right];  //先加右指针的数再把右指针右移,因此右指针属于开区间
                right++;
            }

        }
        while (sum >= s&&left<nums.size())    //由于右指针开区间,存在越界风险,这里讨论的是已经加到最后一位的情况
        {
            minlen = min(minlen, right - left);
            sum -= nums[left];
            left++;
        }
        if (minlen == 10000) return 0;
        else return minlen;

    }
};

这里的代码可以再简洁一点就是如果先加nums[right]再right++的话就不用担心right越界的情况

 

还有第3中方法叫二分查找法,引进了一个新的sum数组,第i个数表示nums数组前i项的和,该方法我个人认为比较复杂,将找最小数组的问题转为找一个临界值的问题,从而可以用常用的更快的查找方法来加快速度,这里就不写了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值