원리 · intermediate

슬라이딩 윈도우

연속 구간에서 조건을 유지하며 좌우를 움직이는 O(n) 패턴.

배우기 · 알고리즘 원리 · 18분 · 6/14 · 슬라이딩윈도우 · 투포인터

이 트랙 목차 (14)
  1. 1. 시간·공간 복잡도 (Big-O) 제대로 읽기
  2. 2. 투포인터: 양끝·같은방향
  3. 3. 해시맵·해시셋: 빠른 조회
  4. 4. 스택·큐: LIFO와 FIFO
  5. 5. 재귀와 이분 탐색
  6. 6. 슬라이딩 윈도우
  7. 7. 동적 계획법 입문 (DP)
  8. 8. 누적합·차분 배열
  9. 9. 그래프 탐색: BFS·DFS
  10. 10. 정렬을 언제 쓰나: 전처리·이분·그리디
  11. 11. 그리디: 탐욕 선택과 반례
  12. 12. 행렬·격자: 인덱싱과 방문
  13. 13. 비트 연산 기초: AND OR XOR · 플래그
  14. 14. 우선순위 큐·힙 감각

한 줄 정의

연속 부분배열·부분문자열에서 오른쪽 끝을 늘리고, 조건이 깨지면 왼쪽 끝을 줄이며 최적·유효 구간을 찾습니다.
본질은 같은 방향 투포인터 + 구간 상태(합, 빈도 맵 등)입니다.

고정 길이 윈도우

길이 k인 구간만 보면 됩니다.

def max_sum_k(arr, k):
    s = sum(arr[:k])
    best = s
    for i in range(k, len(arr)):
        s += arr[i] - arr[i - k]
        best = max(best, s)
    return best

한 칸 밀 때마다 O(1) 갱신 → 전체 O(n).

가변 길이 윈도우

예: “서로 다른 문자가 최대 k개”, “합이 target 이하인 최장 구간”.

function longestAtMostKDistinct(s, k) {
  const freq = new Map();
  let lo = 0, best = 0;
  for (let hi = 0; hi < s.length; hi++) {
    freq.set(s[hi], (freq.get(s[hi]) || 0) + 1);
    while (freq.size > k) {
      const c = s[lo++];
      freq.set(c, freq.get(c) - 1);
      if (freq.get(c) === 0) freq.delete(c);
    }
    best = Math.max(best, hi - lo + 1);
  }
  return best;
}

불변식

루프 진입 시 [lo, hi]항상 유효한 구간이 되게 while로 lo를 당깁니다.

언제 쓰나

함정

  1. lo를 줄일 때 맵·합을 같이 되돌리기
  2. 빈 구간·전체 구간 경계
  3. 고정 길이와 가변 길이를 혼동
  4. 문자 빈도 0인 키를 맵에 남겨 size가 커지는 실수 (JS)

복잡도

각 인덱스가 hi로 한 번, lo로 최대 한 번 이동 → O(n) 시간.
문자종류·해시 공간은 O(Σ) 또는 O(k).

투포인터·해시와의 관계

슬라이딩 = 투포인터 + (자주) 해시 상태.
앞 레슨 두 개를 읽고 오면 이 패턴이 자연스럽게 붙습니다.

관련 짧은 원리

관련 문제