題意#
題目給定由 \( n \) 個正整數組成的陣列,與目標總和 \( x \)。
我們需要求出有幾個「連續的子陣列(Subarray)」其數字總和等於目標值 \( x \)。
思路#
陣列全為正整數具有重要的單調性質:當連續區間加長時,數字總和必然增加。
有了單調遞增的特性,便可使用「雙指標(滑動視窗 Sliding Window)」來達成 \(\mathcal{O}(N)\) 的解法。
設定左指標 l 與右指標 r 起始於陣列最左端:
- 右指標拓展:將
r指標向右推進,將新數字加入區間總和(sum)。 - 左指標收縮:若區間總和「大於」目標值 \( x \),則將左指標
l向右縮減,從sum減去左側數字,直到總和回到不大於 \( x \) 的範圍。 - 結算:調整後,若區間總和剛好等於目標值(
sum == x),則找到一組連續子陣列,將答案計數加一。
雙指標由左至右掃描一次,即可找出所有符合條件的區間。
程式碼#
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>
signed main() { WA();
int n, x; cin >> n >> x;
vector<int> v(n);
for (auto &i : v) cin >> i;
int ans = 0;
// l 為左邊界,r 為右邊界,sum 為目前滑動視窗內的總和
for (int l = 0, r = 0, sum = 0; r < n;) {
// 右指標向右伸展,加入新數字到 sum
sum += v[r++];
// 總和超過目標值 x 時,左指標向右收縮,減去左側數字
while (sum > x) sum -= v[l++];
// 若區間總和精準等於目標 x,則記錄一組答案
if (sum == x) ans++;
}
cout << ans;
}
