力扣:长度最小的子数组

力扣:长度最小的子数组
代码随想录解析地址
题目:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
暴力解法代码:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

sum(和)通过sum+=nums [ j ] 来实现,所以for条件是 j = i

for(int j = i; j < nums.size(); j++)

滑动窗口法:
更加快速寻找到最佳范围。
i 指针指向起始位置
j 指针指向终止位置
相比于暴力解法,滑动窗口法的优势解释:
首先 i j 都为0然后移动 j 寻找最佳位置,起始位置为 0 的最佳范围找到了,再寻找起始位置为 1 的最佳范围,和要大于target 此时将 i 指向的位置后移一位(即寻找起始位置为 1 的最佳范围)j 的位置不动,此时的sum就已经可能大于等于target,若 j 指针为此位置的前一位则sum肯定小于target,所以 j 指针就从此位置开始,来判断sum是否大于等于target。(暴力解法是将 j 置于 i 的位置开始寻找最佳范围(麻烦))
**即:**首先锁定i,移动 j 寻找到可用序列,然后锁定 j 移动 i 在这个可用序列中寻找到最短可用序列
通过思考题目来想思路,不要想窗口。
整体思路:
j 不断后移寻找到最适位置,然后进入while对初始化的数据(length,result)进行操作,此时在这个起始位置的最佳范围已经找到,要找下一个位置了,那么此时 i 后移一位,sum更正,此时又进行判断sum是否大于等于target,如果是又进行上面的这个操作,如果不是那么移动 j 找到结束位置。
题目条件:如果不存在符合条件的子数组,返回 0 。
此点通过 result 是否被赋值来判断。
代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
       int result = INT32_MAX;
       int length = 0;
       int i = 0;
       int sum = 0;
       for(int j = 0; j < nums.size(); j++){
           sum += nums[j];
           while(sum >= target){
               length = j - i + 1;
               result = result >= length? length:result;
                sum -= nums[i++];
           }
       }
       return result == INT32_MAX? 0:result;
    }
};

自己解法:

  1. [ i , j ]构成范围
    1. 一开始范围是0~ -1表示没有开始
  2. 范围总和小于目标值
    1. j出现越界,直接返回
    2. 没有越界,则加入下一个值
  3. 范围总和大于目标值
    1. 是否更新len
    2. 此时的范围:首元素向后移动一个单位
    3. 更新sum
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i, j = -1;
        i = 0;
        int sum = 0;
        int len = INT_MAX;
        while(i <= nums.size()-1 && j < int(nums.size())){
            if(sum < target) {
                if(++j == nums.size()) {
                    if(len == INT_MAX) return 0;
                    return len;
                }
                else sum += nums[j];
            }   
            else {
                if(len  > j-i+1){
                    len = j-i+1;
                }
                sum-=nums[i++];
            }
        }
        return len;
    }
};
j < int(nums.size()

类型强制转换的原因:j有符号整型,且可能为负值,nums.size()为无符号整型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值