同向双指针
长度最小的子数组
力扣209
#define MIN(a, b) ((b) < (a) ? (b) : (a))
int minSubArrayLen(int target, int* nums, int numsSize)
{
int ans = numsSize + 1;
int left = 0;
int right = 0;
int sum = 0;
for (right = 0; right < numsSize; right++)
{
sum += nums[right];
while (sum - nums[left++] >= target)
{
sum -= nums[left++];
}
if (sum >= target)
{
ans = MIN(numsSize + 1, right - left + 1);
}
}
return ans <= numsSize ? ans : 0;
}
枚举右下标同时右移左下标
以下是对这段代码的解析:
一、宏定义部分
#define MIN(a, b) ((b) < (a)? (b) : (a))
- 这是一个宏定义,用于求两个数中的最小值。它接受两个参数
a
和b
,然后通过三目运算符? :
来判断,如果b
小于a
,就返回b
,否则返回a
。这种宏定义在代码中可以方便地用于比较两个值的大小并获取较小值。
- 这是一个宏定义,用于求两个数中的最小值。它接受两个参数
二、函数minSubArrayLen
部分
- 变量初始化
int ans = numsSize + 1;
:这里初始化ans
为numsSize + 1
,它将用于记录满足条件的子数组的最小长度。初始化为numsSize + 1
是因为实际的最小长度不会超过numsSize
,这样初始化方便后续比较更新。int sum = 0;
:用于记录当前子数组的元素总和,初始化为0。int left = 0;
和int right = 0;
:这两个变量分别作为滑动窗口(子数组)的左右端点,初始时都指向数组的起始位置。
- 外层
for
循环(枚举子数组右端点)for (right = 0; right < numsSize; right++)
:这个循环的目的是枚举子数组的右端点。每次循环,right
指针都会向右移动一位。- 在循环内部,首先执行
sum += nums[right];
,这是将当前right
指针指向的元素加入到子数组的总和sum
中。
- 内层
while
循环(缩小子数组长度)while (sum - nums[left] >= target)
:这个循环的目的是在当前子数组总和大于等于target
时,尽量缩小子数组的长度。通过不断地将左端点left
向右移动(sum -= nums[left++];
),来减去子数组最左边的元素,直到子数组总和小于target
为止。
- 更新最小长度
if (sum >= target)
:当子数组总和大于等于target
时,通过ans = MIN(ans, right - left + 1);
来计算当前子数组的长度(right - left + 1
),并使用之前定义的MIN
宏来获取当前长度和之前记录的最小长度ans
中的较小值,从而更新ans
。
- 函数返回值
return ans <= numsSize? ans : 0;
:最后,函数返回ans
。如果ans
小于等于numsSize
,说明找到了满足条件的子数组,直接返回ans
;如果ans
大于numsSize
,则表示没有找到满足条件的子数组,返回0。