슬라이딩 윈도우는 배열, 리스트 또는 문자열과 같은 연속된 데이터 구조에서 부분집합을 효율적으로 탐색하거나 계산하기 위해 사용되는 알고리즘 기법이다.
특히, 고정 길이 또는 가변 길이의 부분 집합에 대해 반복적으로 계산할 때 유용하다.
슬라이딩 윈도우는 데이터를 처음부터 끝가지 순회하면서, 고정된 크기 또는 조건에 따라 움직이는 윈도우를 유지한다.
초기화
윈도우 확장
조건 검증
윈도우 축소
반복
슬라이딩 윈도우는 다음과 같은 형태의 문제에 주로 사용된다.
target
인 부분 배열의 시작과 끝 찾기.크기가 k인 모든 부분 배열의 합 중 최대값을 구하라.
public class SlidingWindowFixed {
public static int maxSum(int[] nums, int k) {
int n = nums.length;
int currentSum = 0;
// 초기 윈도우 설정
for (int i = 0; i < k; i++) {
currentSum += nums[i];
}
int maxSum = currentSum;
// 윈도우를 슬라이드
for (int i = k; i < n; i++) {
currentSum += nums[i] - nums[i - k]; // 새 값을 추가하고 오래된 값을 제거
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}
public static void main(String[] args) {
int[] nums = {1, 3, 2, 5, 1, 1, 2, 3};
int k = 3;
System.out.println("최대 부분 합: " + maxSum(nums, k)); // 출력: 10
}
}
부분 배열의 합이 target
이하인 경우의 최대 길이를 구하라.
public class SlidingWindowVariable {
public static int maxLength(int[] nums, int target) {
int start = 0; // 윈도우의 시작점
int currentSum = 0;
int maxLength = 0;
for (int end = 0; end < nums.length; end++) {
currentSum += nums[end]; // 새 값을 윈도우에 추가
// 조건을 만족하지 않으면 윈도우를 축소
while (currentSum > target) {
currentSum -= nums[start];
start++;
}
// 최대 길이 갱신
maxLength = Math.max(maxLength, end - start + 1);
}
return maxLength;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
int target = 7;
System.out.println("최대 길이: " + maxLength(nums, target)); // 출력: 2
}
}
고유 문자의 개수가 k
이하인 가장 긴 부분 문자열을 찾아라.
import java.util.HashMap;
public class SlidingWindowString {
public static int longestSubstring(String s, int k) {
int start = 0;
int maxLength = 0;
HashMap<Character, Integer> charCount = new HashMap<>();
for (int end = 0; end < s.length(); end++) {
char endChar = s.charAt(end);
charCount.put(endChar, charCount.getOrDefault(endChar, 0) + 1);
// 조건을 만족하지 않으면 윈도우 축소
while (charCount.size() > k) {
char startChar = s.charAt(start);
charCount.put(startChar, charCount.get(startChar) - 1);
if (charCount.get(startChar) == 0) {
charCount.remove(startChar);
}
start++;
}
// 최대 길이 갱신
maxLength = Math.max(maxLength, end - start + 1);
}
return maxLength;
}
public static void main(String[] args) {
String s = "abcba";
int k = 2;
System.out.println("가장 긴 부분 문자열 길이: " + longestSubstring(s, k)); // 출력: 3 ("bcb")
}
}