#슬라이딩 윈도우

구간을 효율적으로 옮기며 부분 배열의 상태를 관리하는 문제를 다룬다. 현재 3개의 풀이가 있다.

슬라이딩 윈도우 학습 가이드

필요한 주제만 펼쳐서 연속 구간을 효율적으로 관리하고, 매번 다시 계산하는 작업을 줄이는 방법을 학습할 수 있습니다.

슬라이딩 윈도우 기본 개념

슬라이딩 윈도우는 배열이나 문자열의 연속된 구간을 현재 상태로 유지하면서 경계를 이동하는 기법입니다. 새 구간을 처음부터 다시 계산하는 대신, 빠져나가는 값과 들어오는 값만 반영합니다.

길이 4인 고정 윈도우가 한 칸 이동하며 왼쪽 문자를 제거하고 오른쪽 문자를 추가하는 그림
고정 크기 윈도우는 한 칸 이동할 때 나가는 원소 하나와 들어오는 원소 하나만 갱신합니다.
  • 윈도우: 현재 검사 중인 연속 구간
  • left: 구간의 시작 경계
  • right: 새 원소를 포함하는 끝 경계
  • 윈도우 상태: 합계, 빈도, 종류 수처럼 현재 구간에서 유지할 정보
고정 길이 윈도우

구간 길이가 `k`로 정해져 있으면 첫 윈도우를 한 번 계산하고, 이후 매 단계에서 이전 구간의 왼쪽 원소를 빼고 새 오른쪽 원소를 더합니다.

window_sum = sum(nums[:k])
best = window_sum

for right in range(k, len(nums)):
    window_sum += nums[right]
    window_sum -= nums[right - k]
    best = max(best, window_sum)

합계나 평균, 특정 길이의 부분 문자열 빈도처럼 같은 크기의 구간을 모두 확인하는 문제에 적합합니다. 각 원소를 상수 번씩만 처리하므로 전체 계산을 `O(n)`에 할 수 있습니다.

가변 길이 윈도우

구간의 길이가 조건에 따라 달라지면 `right`를 늘려 새 원소를 포함하고, 조건을 만족하지 않거나 가능한 구간을 더 줄일 수 있을 때 `left`를 이동합니다.

right 경계를 늘려 구간을 확장하고 조건이 깨지면 left 경계를 이동해 구간을 줄이는 가변 윈도우 그림
오른쪽으로 확장해 후보를 포함하고, 조건에 따라 왼쪽을 이동해 유효 구간을 유지합니다.
  1. `right` 원소를 현재 상태에 추가합니다.
  2. 현재 구간이 조건을 만족하는지 확인합니다.
  3. 조건이 깨졌다면 회복될 때까지 `left` 원소를 제거하고 경계를 이동합니다.
  4. 조건이 맞는 구간의 길이나 점수를 정답과 비교합니다.

각 포인터가 왼쪽에서 오른쪽으로 한 번씩만 이동하는 구조라면 안쪽에 `while`문이 있어도 전체 시간은 보통 `O(n)`입니다.

문자 빈도 윈도우: 순열·애너그램 찾기

문자열 `s1`의 순열은 길이가 `len(s1)`이고 문자별 등장 횟수가 같은 부분 문자열입니다. 따라서 `s2`를 길이 `len(s1)`인 고정 윈도우로 이동하면서 빈도 상태를 비교하면 됩니다.

문자열 ab의 문자 빈도 a:1, b:1과 윈도우 ba의 빈도가 같음을 비교하는 그림
문자 순서는 달라도 윈도우의 문자별 빈도가 목표 문자열과 같으면 순열입니다.
  • 문자 종류가 소문자 알파벳 26개로 제한되어 빈도 배열 크기는 상수입니다.
  • 윈도우가 이동하면 나간 문자의 빈도를 1 줄이고 들어온 문자의 빈도를 1 늘립니다.
  • 빈도 배열 26칸이 모두 같으면 해당 윈도우는 순열입니다.
자주 하는 실수
  • 문제에서 요구한 연속 구간을 부분수열과 혼동하는 경우
  • 윈도우가 이동할 때 빠져나간 원소의 상태를 제거하지 않는 경우
  • 고정 길이 문제에서 첫 윈도우를 포함하거나 마지막 윈도우를 빠뜨리는 경우
  • 가변 윈도우에서 조건이 만족될 때와 깨질 때 어느 경계를 움직일지 잘못 정하는 경우
  • 문자 순열 판정에서 길이 확인을 생략하거나 빈도 갱신 순서를 혼동하는 경우

전체 문제 풀이 보기