与えられた配列 A に対して、連続部分列のうち、和が K 以下のものの個数を求める という問題です。
🧠 解法の考え方:しゃくとり法 (Two Pointers)
2つのポインタ left と right を使って、連続した部分列を動的に管理します。
条件を満たす right の最大範囲を求めて、一括で個数を数えます。
N = 7, K = 50
A = [11, 12, 16, 22, 27, 28, 31]
left = 0, right = 0, sum = 0, count = 0
// A[0] + A[1] + A[2] = 11 + 12 + 16 = 39 <= 50 → OK
// A[3] = 22 を加えると 39 + 22 = 61 > 50 → OUT
[11, 12, 16, 22, 27, 28, 31]
↑ ↑ ↑
l r = 3 (STOP)
right - left = 3 - 0 = 3 個([11], [11,12], [11,12,16])
count = 3
sum = 39 - 11 = 28
right = 3 のまま → A[3] = 22 を追加 → sum = 50 ✅
[11, 12, 16, 22, 27, 28, 31]
↑ ↑ ↑
l r = 4 (STOP)
部分列: [12], [12,16], [12,16,22]
count += 3 → 合計6
sum = 50 - 12 = 38
right = 4 → A[4] = 27 を追加 → sum = 65 ❌ → right動かず
[11, 12, 16, 22, 27, 28, 31]
↑ ↑
l r = 4 (STOP)
部分列: [16], [16,22] → 合計2個
count += 2 → 合計8
sum = 38 - 16 = 22
A[4] = 27 → sum = 49 ✅ → right = 5
[11, 12, 16, 22, 27, 28, 31]
↑ ↑
l r = 5
部分列: [22], [22,27]
count += 2 → 合計10
sum = 49 - 22 = 27
A[5] = 28 → sum = 55 ❌ → right動かず
[11, 12, 16, 22, 27, 28, 31]
↑ ↑
l r = 5
部分列: [27]
count += 1 → 合計11
sum = 27 - 27 = 0
A[5] = 28 → sum = 28 ✅ → right = 6
A[6] = 31 → sum = 59 ❌ → right動かず
[11, 12, 16, 22, 27, 28, 31]
↑ ↑
l r = 6
部分列: [28]
count += 1 → 合計12
sum = 28 - 28 = 0
A[6] = 31 → sum = 31 ✅ → right = 7(末尾)
[11, 12, 16, 22, 27, 28, 31]
↑ ↑
l r = 7
部分列: [31]
count += 1 → 合計13
処理名
内容
計算量
入力読み取り
fs.readFileSync() で全行読み込み
O(N)
ポインタ移動
while (sum + A[right] <= K)
O(N)
カウント更新
count += right - left
O(1)
合計管理
sum += A[right], sum -= A[left]
O(1)
ポインタ left と right で区間を管理
条件を満たす最大 right を探索
その区間の全ての部分列は条件を満たすため、一括でカウント