정수 배열 arr를 첫 번째 인수로, 그리고 num(배열 길이보다 작은 수)을 두 번째 인수로 받는 JavaScript 함수를 작성해야 합니다. 이 함수는 배열 안에서 연속된 num개의 숫자로 이루어진 모든 구간(윈도우)의 평균값을 담은 새로운 배열을 만들어 반환해야 합니다.
문제 이해하기
예를 들어 입력 배열과 숫자가 다음과 같다고 가정해 보겠습니다.
const arr = [1, 2, 3, 4, 5];
const num = 2;
크기가 2인 연속된 윈도우는 (1, 2), (2, 3), (3, 4), (4, 5)로 총 네 가지이므로, 출력 결과는 다음과 같아야 합니다.
const output = [1.5, 2.5, 3.5, 4.5];
슬라이딩 윈도우 기법이란?
이 문제는 슬라이딩 윈도우(Sliding Window) 기법으로 효율적으로 해결할 수 있습니다. 매번 새로운 구간의 합을 처음부터 다시 계산하는 대신, 이전 구간의 합에서 왼쪽 끝 요소를 빼고 오른쪽에 새로 들어오는 요소를 더하면 됩니다. 이렇게 하면 불필요한 반복 계산을 줄여 시간 복잡도를 O(n)으로 유지할 수 있습니다.
예제 코드
const arr = [1, 2, 3, 4, 5];
const num = 2;
const findContiniousAverage = (arr = [], num = 1) => {
if(num > arr.length){
return [];
};
const res = [];
let sum = 0;
let left = 0, right = 0;
for(; right < num; right++){
sum += arr[right];
};
res.push(sum / num);
for(; right < arr.length; right++, left++){
sum -= arr[left];
sum += arr[right];
res.push(sum / num);
};
return res;
};
console.log(findContiniousAverage(arr, num));
console.log(findContiniousAverage(arr));
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ 1.5, 2.5, 3.5, 4.5 ]
[ 1, 2, 3, 4, 5 ]
코드 동작 원리
1. 예외 처리: num이 배열 길이보다 크면 유효한 윈도우를 만들 수 없으므로 빈 배열을 반환합니다.
2. 첫 번째 윈도우 계산: 첫 번째 for 루프에서 맨 앞의 num개 요소의 합을 구하고, 이를 num으로 나눈 평균을 결과 배열에 추가합니다.
3. 윈도우 이동: 두 번째 루프에서는 윈도우를 한 칸씩 오른쪽으로 밀면서, 빠져나가는 왼쪽 요소(arr[left])는 빼고 새로 들어오는 오른쪽 요소(arr[right])는 더한 뒤 평균을 기록합니다.
4. 기본값 동작: num이 전달되지 않으면 기본값 1이 적용되어 각 요소 자체가 평균이 되므로, 원본 배열과 동일한 값이 반환됩니다.