C++算法练习-day4——209.长度最小的子数组

题目来源:. - 力扣(LeetCode)

题目思路分析

给定一个整数数组 nums 和一个整数 target,题目要求找到数组中最短的连续子数组,其和大于等于 target,并返回其长度。如果不存在这样的子数组,则返回 0。

这个问题可以通过滑动窗口算法来解决。滑动窗口算法是一种用于处理数组问题的常用技巧,特别适用于在数组中寻找子数组或子串的问题。

解题思路如下:

  1. 初始化两个变量:sum 用于记录当前窗口内元素的和,k 用于记录当前窗口的长度。
  2. 初始化 ans 为数组长度加一(n+1),用于记录满足条件的最小子数组长度。这样做的目的是在后续比较时能够方便地判断是否存在满足条件的子数组。
  3. 使用一个循环遍历数组,每次将当前元素加入 sum,并增加 k(窗口长度)。
  4. 在每次循环中,检查 sum 是否大于等于 target
    • 如果是,说明找到了一个满足条件的子数组。此时,更新 ans 为当前 ans 和 k 中的较小值,并尝试通过缩小窗口来寻找更短的子数组。
    • 如果不是,继续扩展窗口(即继续遍历数组)。
  5. 缩小窗口的方法是通过减少 sum(减去窗口最左边的元素)并减少 k(窗口长度减一)来实现的。
  6. 循环结束后,检查 ans 是否仍为 n+1,如果是,则说明不存在满足条件的子数组,返回 0;否则,返回 ans

代码实例及注解

实例:

#include <vector>  
#include <algorithm> // 用于 std::min 函数(可选,因为这里可以手动比较)  
  
class Solution {  
public:  
    int minSubArrayLen(int target, std::vector<int>& nums) {  
        int n = nums.size(); // 记录数组长度  
        int ans = n + 1; // 初始化结果,设置为一个不可能达到的值(数组长度加一)  
        int sum = 0; // 记录当前窗口内元素的和  
        int k = 0; // 记录当前窗口的长度  
          
        // 遍历数组  
        for (int i = 0; i < n; i++) {  
            sum += nums[i]; // 将当前元素加入窗口和  
            ++k; // 增加窗口长度  
              
            // 检查窗口和是否大于等于目标值  
            while (sum >= target) {  
                // 更新最小子数组长度  
                ans = std::min(ans, k); // 或者使用 ans = (ans < k) ? ans : k;  
                  
                // 尝试缩小窗口  
                sum -= nums[i - k + 1]; // 减去窗口最左边的元素(注意下标计算)  
                --k; // 减少窗口长度  
            }  
        }  
          
        // 返回结果,如果不存在满足条件的子数组,则返回 0  
        return (ans == n + 1) ? 0 : ans;  
    }  
};

注解

  • std::vector<int>& nums:输入参数,一个整数类型的向量引用。
  • int target:输入参数,目标值。
  • int n = nums.size():记录数组的长度。
  • int ans = n + 1:初始化结果变量,设置为一个不可能达到的值(数组长度加一),用于后续比较。
  • int sum = 0:记录当前窗口内元素的和。
  • int k = 0:记录当前窗口的长度。
  • for (int i = 0; i < n; i++):遍历数组。
  • sum += nums[i]:将当前元素加入窗口和。
  • ++k:增加窗口长度。
  • while (sum >= target):当窗口和大于等于目标值时,执行循环体内的代码。
  • ans = std::min(ans, k):更新最小子数组长度。
  • sum -= nums[i - k + 1]:尝试缩小窗口,减去窗口最左边的元素(注意下标计算,避免数组越界)。
  • --k:减少窗口长度。
  • return (ans == n + 1) ? 0 : ans:返回结果,如果不存在满足条件的子数组,则返回 0。

知识点摘要

  1. 滑动窗口算法:一种用于处理数组或字符串中连续子数组/子串问题的常用技巧。通过维护一个窗口(即连续的子数组/子串),并动态地调整窗口的大小和位置来寻找满足条件的解。

  2. 数组和字符串的下标操作:在 C++ 中,数组和字符串的下标从 0 开始。在处理窗口最左边的元素时,需要注意下标的正确计算,以避免数组越界。

  3. 条件判断与更新操作:在算法中,经常需要根据当前的状态(如窗口和与目标值的关系)来更新变量(如最小子数组长度)或调整窗口的大小和位置。

  4. 算法的时间复杂度:该算法的时间复杂度为 O(n),其中 n 是数组的长度。因为每个元素最多被访问两次:一次是在窗口扩展时加入窗口和,另一次是在窗口缩小时被移除。

通过本文的讲解和代码实例,相信读者已经对如何使用滑动窗口算法求解最小子数组长度有了更深入的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Neophyte0608

你的鼓励将使我创作学的更加快乐

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

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

打赏作者

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

抵扣说明:

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

余额充值