{}연습장
대시보드학습스킬 경로문제모의고사라이브 코테복습데이터
← 학습 목록로드맵에서 보기
Lv.2 중급 준비

슬라이딩 윈도우

연속 구간을 창문 밀듯 갱신 — 빠진 값 빼고 새 값만 더하기. 고정 크기에서 시작해 가변 크기(두 포인터 결합)로 확장합니다.

지문 신호“연속한 K개”“연속 부분 배열”“최장/최단 구간”
0/8 해결
1

눈으로 보기

재생을 누르고 단계별로 동작을 따라가세요
2
5
1
4
3
2
합 = —최댓값 = —
1/7연속한 3개의 합의 최댓값을 찾습니다. 매번 다시 더하면 O(N·K) — 창문을 밀며 "빠진 값 빼고 새 값만 더하면" O(N)입니다.
■ 앰버 테두리 = 현재 창문(k=3)빠진 값 −, 새 값 + 만으로 갱신
2

개념 이해

핵심 패턴 코드는 손으로 따라 쳐 보는 것을 권장
1 / 8

비유로 이해하기

신문에 숫자가 한 줄로 인쇄되어 있고, 그 위에 구멍이 세 칸 뚫린 종이 액자를 올려놓았다고 생각해 보세요. 액자를 오른쪽으로 한 칸 밀면 왼쪽 끝의 숫자 하나가 가려지고, 오른쪽 끝에서 숫자 하나가 새로 보입니다. 나머지 숫자는 그대로입니다. 그래서 액자 안 숫자의 합을 다시 구할 때 전부 더할 필요 없이, 사라진 값을 빼고 새로 들어온 값을 더하면 됩니다.

슬라이딩 윈도우는 연속한 구간을 훑을 때, 구간을 매번 새로 계산하지 않고 한 칸 밀 때의 변화량만 갱신하는 기법입니다.

  • 액자 위치 1: [3 1 4] 1 5 → 합 8
  • 한 칸 밀기: 3이 나가고 1이 들어옴 → 8 - 3 + 1 = 6
  • 다시 밀기: 1이 나가고 5가 들어옴 → 6 - 1 + 5 = 10

[3, 1, 4, 1, 5]에서 연속한 3개의 합이 가장 큰 구간을 손으로 찾아봅니다.

단계 액자가 덮은 구간 나간 값 / 들어온 값 합 지금까지 최대
시작 3, 1, 4 (첫 창은 그냥 다 더함) 8 8
1 1, 4, 1 3 나감 / 1 들어옴 8 - 3 + 1 = 6 8
2 4, 1, 5 1 나감 / 5 들어옴 6 - 1 + 5 = 10 10

정직하게 계산하면 구간마다 3번씩 더해 총 9번이지만, 밀면서 계산하면 첫 창 3번 + 이후 한 칸당 2번뿐입니다. 원소가 10만 개이고 구간 길이가 1000이면 이 차이가 그대로 시간 초과와 통과를 가릅니다.

고정 크기 창의 골격은 "첫 창을 만들고 → 한 칸씩 밀고 → 기록한다"입니다.

  1. 첫 창만 정직하게 채웁니다 — 인덱스 0부터 k-1까지 전부 더합니다.
let sum = 0;
for (let i = 0; i < k; i++) sum += arr[i];
let best = sum;
  1. 한 칸 밀 때는 빼고 더하기만 합니다 — 나가는 값은 arr[i - k], 들어오는 값은 arr[i]입니다.
sum += arr[i] - arr[i - k]; // 미는 비용은 O(1)
  1. 밀 때마다 답을 갱신합니다.
best = Math.max(best, sum);

전체 코드 — "연속 K개 합의 최댓값":

function maxWindowSum(arr: number[], k: number): number {
  // 1단계: 첫 창만 정직하게
  let sum = 0;
  for (let i = 0; i < k; i++) sum += arr[i];
  let best = sum;
  // 2~3단계: 한 칸씩 밀며 갱신하고 기록
  for (let i = k; i < arr.length; i++) {
    sum += arr[i] - arr[i - k];
    best = Math.max(best, sum);
  }
  return best;
}
  • 지문에 "연속한 K개", "연속 부분 배열", "연속한 부분 문자열"이 보이면 이 유형입니다. 연속이 아니라 아무 원소나 골라도 되는 문제는 슬라이딩 윈도우가 아닙니다.
  • "조건을 만족하는 가장 긴 / 가장 짧은 연속 구간의 길이" — 창 크기가 변하는 가변 윈도우 신호입니다.
  • 대표 문제 상황: 연속 K일 매출의 최대 합, 서로 다른 문자가 K종 이하인 최장 부분 문자열, 합이 목표 이하인 최장 구간.
  • 이중 루프로 모든 구간을 다시 더하다 시간 초과가 났다면 거의 이 기법으로 바꿔야 하는 경우입니다.

가변 크기 윈도우 (두 포인터 결합) — 조건을 만족하는 최장/최단 구간은 창 크기가 변합니다. 오른쪽을 늘리다 조건이 깨지면 왼쪽을 줄입니다.

// 합이 K 이하인 최장 연속 구간
function longestUnderK(arr: number[], K: number): number {
  let left = 0, sum = 0, best = 0;
  for (let right = 0; right < arr.length; right++) {
    sum += arr[right];                       // ① 오른쪽 확장
    while (sum > K) sum -= arr[left++];      // ② 조건 깨지면 왼쪽 축소
    best = Math.max(best, right - left + 1); // ③ 유효한 상태에서 기록
  }
  return best;
}

확장 → 축소 → 기록의 3박자를 몸에 익히세요. left와 right 모두 최대 N번 움직이므로 O(N)입니다.

창 안의 구성이 조건인 경우 — "서로 다른 문자 K종 이하 최장 부분 문자열"처럼 창 안에 무엇이 들어 있는지가 조건이면, 창과 함께 Map(문자 → 개수)을 유지합니다.

const count = new Map<string, number>();
count.set(ch, (count.get(ch) ?? 0) + 1);              // 들어올 때
const n = count.get(out)! - 1;                        // 나갈 때
n === 0 ? count.delete(out) : count.set(out, n);      // 0이면 삭제해야 size가 맞음
상황 창 크기 유지할 상태
연속 K개의 합/평균 고정 합 하나
합이 K 이하인 최장 구간 가변 합 + left
서로 다른 값 K종 이하 가변 Map(값 → 개수) + left
특정 문자를 모두 포함하는 최단 구간 가변 Map + 충족한 종류 수
  • 축소를 if로 한 번만 함 — 조건이 회복될 때까지 while로 반복해야 합니다.
if (sum > K) sum -= arr[left++];    // 잘못: 한 번 줄여도 여전히 초과일 수 있음
while (sum > K) sum -= arr[left++]; // 고침: 회복될 때까지
  • 기록 시점 오류: 조건이 깨진 상태에서 best를 갱신 (③은 반드시 축소가 끝난 유효 상태에서).
sum += arr[right];
best = Math.max(best, right - left + 1); // 잘못: 아직 sum > K일 수 있음
while (sum > K) sum -= arr[left++];
  • 음수가 섞인 배열에서 "합" 기반 가변 윈도우 사용 — 오른쪽을 늘려도 합이 커진다는 보장이 없어(단조가 아니라) 성립하지 않습니다. 그때는 누적합 + 해시로 전환합니다.
  • 고정 창에서 첫 창을 만들기 전에 밀기 시작 — 인덱스 k-1까지는 채우기 단계이고, 미는 루프는 i = k부터입니다.
  • Map으로 구성을 셀 때 개수가 0이 된 키를 지우지 않음 — map.size가 실제 종류 수보다 크게 나옵니다.
  • 왜 O(N)인가: 가변 윈도우는 이중 루프처럼 보이지만, left는 감소하지 않고 전체 실행 동안 최대 N번만 증가합니다. 안쪽 while의 총 실행 횟수가 N을 넘지 않으므로 전체가 O(N)입니다. 이런 계산 방식을 분할 상환(amortized) 분석이라고 합니다.
  • 단조성이 성립 조건: 가변 윈도우가 옳으려면 "창을 늘리면 지표가 나빠지고, 줄이면 좋아진다"는 방향성이 있어야 합니다. 모든 값이 양수인 합, 서로 다른 값의 개수는 이 성질을 만족합니다. 음수가 섞인 합은 만족하지 않습니다.
  • 음수가 있을 때의 대안: 누적합 prefix[i]를 만들고 "합이 정확히 K인 구간"은 prefix[i] - K를 해시에서 찾는 방식으로 O(N)에 처리합니다. "합이 K 이하인 최장"처럼 부등호 조건이면 단조 덱(deque)이나 이진 탐색을 얹습니다.
  • 최댓값/최솟값 창: 창 안의 최댓값을 계속 알아야 하면 합처럼 빼고 더할 수 없습니다. 인덱스를 담는 단조 덱을 유지해 창 밖으로 나간 인덱스를 앞에서 버리는 방식으로 O(N)을 만듭니다.

시각화로 "빼고 더하기"의 리듬을 본 뒤, 고정 크기 → 가변 크기(합 조건) → 구성 조건(Map 결합) 순으로. 이 유형은 이 사이트에 문제가 많으니 사다리를 끝까지 오르세요.

3

문제로 확인

난이도 순서대로 8문제 — 막히면 개념으로 돌아왔다 다시
1연속 부분 수열 합 개수#042다음 풀 문제쉬움2K일 연속 최대 매출#055쉬움3K개 연속 합 최댓값#085쉬움4연속 부분 수열 합 시작 인덱스#043중간5생산 할당량 최단 연속 구간#056중간6중복 없는 최장 부분 배열#057중간7예산 내 최장 연속 구매#093중간8순환 배송 트랙의 최대 이익 구간#028어려움
← 이전 토픽 · Lv.2투 포인터다음 토픽 · Lv.2 →이진 탐색