题目背景
这道题是典型的滑动窗口问题,核心在于寻找满足特定条件的最短子数组。在笔试或面试中,这类题目考察的是对双指针技巧的掌握程度以及边界情况的处理能力。
解题思路
我们使用两个指针 prev 和 cur 来维护一个动态窗口。cur 负责向右扩展以累加数值,prev 负责在满足条件时向左收缩以尝试缩短窗口长度。
具体流程如下:
- 初始化:定义
sum记录当前窗口内的元素和,初始化为 0。左右指针均指向数组起始位置。 - 扩展窗口:移动
cur指针,将新元素加入sum。当sum大于等于目标值x时,说明当前窗口可能是一个候选解。 - 收缩窗口:一旦满足条件,进入内层循环。此时我们需要尝试缩小窗口以找到更优解(即更短的长度)。每次移除
prev指向的元素并移动prev,同时更新最优解记录。 - 记录结果:比较当前窗口长度与已记录的最优长度。如果当前更短,或者长度相同但起始位置更靠前,则更新结果索引。
- 结束条件:当
cur遍历完整个数组后,算法结束。
这里有个细节需要注意:题目通常要求输出 1-based 索引,而代码内部处理多用 0-based,最后输出时需做转换。
代码实现
下面是完整的 C++ 实现,包含了必要的注释来说明关键逻辑。
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 输入处理:读取数组长度 n 和目标值 x
int n, x;
cin >> n >> x;
vector<int> arr(n, 0);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// 用于保存最终结果的索引 [start, end]
// 初始化为 -1 表示尚未找到有效区间,这里用 0 配合判断逻辑也可
int index[2] = {0};
bool found = false;
cur = ;
prev = ;
sum = ;
(cur < n) {
sum += arr[cur];
(sum >= x) {
(!found) {
index[] = prev;
index[] = cur;
found = ;
} {
currentLen = index[] - index[];
newLen = cur - prev;
(newLen < currentLen || (newLen == currentLen && prev < index[])) {
index[] = prev;
index[] = cur;
}
}
sum -= arr[prev++];
}
cur++;
}
(found) {
cout << index[] + << << index[] + << endl;
} {
cout << << << << endl;
}
;
}


