## 🌟 문제
[코딩테스트 연습 - 할인 행사 \| 프로그래머스 스쿨](https://school.programmers.co.kr/learn/courses/30/lessons/131127)
회원하는 제품을 원하는 수량만큼 할인받을 수 있는 회원 등록 시작 날짜의 총 일수를 구하는 문제.
## 🌟 풀이
10일이라는 고정된 구간 안에서 조건을 만족하는지 확인해야 하기 때문에 슬라이딩 윈도우 방식을 사용했다. 원하는 제품과 수량을 Map으로 관리하면서, 윈도우가 이동할 때마다 빠지는 제품은 필요 수량을 다시 증가시키고, 들어오는 제품을 감소시키는 방식이다.
Map의 모든 값이 0 이하가 되면 원하는 제품을 모두 구매할 수 있는 것이므로 정답을 증가시킨다. 헷갈렸던 것은 wantMap의 value 합이 0인 것으로 정답 여부를 판단하면 안된다는 것인데, 할인 개수가 필요 개수보다 더 많을 수 있기 때문이다. 운이 좋으면 필요 개수가 양수인 것이 있는데도 합이 0이 나올 수 있기 때문에 모든 값들이 0 이하인지를 확인해줘야 했다.
> **시간 복잡도**
> 슬라이딩 윈도우로 discount 배열을 한번 순회하기 때문에 O(N).
> 매 윈도우마다 every를 이용해서 Map의 값을 확인하기 때문에 엄밀히 말하면 최대 O(10 * N)인데, 실질적으로는 O(N)
```javascript
function solution(want, number, discount) {
// 원하는 제품 정보 Map 초기화
const wantMap = new Map();
for (let idx = 0; idx < want.length; idx++) {
wantMap.set(want[idx], number[idx]);
}
// 슬라이딩 윈도우에 필요한 변수들 정의
let answer = 0;
// 첫번째 윈도우 처리
for (let day = 0; day <= 9; day++) {
const product = discount[day];
if (wantMap.has(product)) {
wantMap.set(product, wantMap.get(product) - 1);
}
}
if ([...wantMap.values()].every((num) => num <= 0)) {
answer += 1;
}
// 슬라이딩 윈도우
for (let idx = 0; idx < discount.length - 10; idx++) {
// 앞의 것 빼기
const first = discount[idx];
if (wantMap.has(first)) {
wantMap.set(first, wantMap.get(first) + 1);
}
// 뒤의 것 추가하기
const last = discount[idx + 10];
if (wantMap.has(last)) {
wantMap.set(last, wantMap.get(last) - 1);
}
// 가입 가능 여부 확인
if ([...wantMap.values()].every((num) => num <= 0)) {
answer++;
}
}
return answer;
}
```