문제 상황
배열을 인수로 받아 새로운 배열을 반환하는 JavaScript 함수를 작성해야 합니다. 이때 반환되는 배열의 첫 번째 요소는 입력 배열에서 가장 작은 값(최솟값)이어야 하고, 두 번째 요소는 가장 큰 값(최댓값)이어야 합니다.
예제 코드
다음은 reduce() 메서드를 활용한 해결 코드입니다.
const arr = [56, 34, 23, 687, 2, 56, 567];
const findMinMax = (arr = []) => {
const creds = arr.reduce((acc, val) => {
let [smallest, greatest] = acc;
if (val > greatest) {
greatest = val;
}
if (val < smallest) {
smallest = val;
}
return [smallest, greatest];
}, [Infinity, -Infinity]);
return creds;
};
console.log(findMinMax(arr));실행 결과
[2, 687]
코드 설명
이 코드의 핵심은 배열의 reduce() 메서드입니다. 동작 원리를 단계별로 살펴보면 다음과 같습니다.
- 초기 누적값을
[Infinity, -Infinity]로 설정합니다. 첫 번째 요소는 최솟값 후보, 두 번째 요소는 최댓값 후보 역할을 합니다. - 배열의 각 요소(
val)를 순회하면서 현재 최댓값보다 크면 최댓값을 갱신하고, 현재 최솟값보다 작으면 최솟값을 갱신합니다. - 모든 요소의 순회가 끝나면 갱신된
[최솟값, 최댓값]배열이 최종 결과로 반환됩니다.
이 방식은 배열을 한 번만 순회하므로 시간 복잡도가 O(n)으로 효율적이며, 빈 배열이 전달되더라도 [Infinity, -Infinity]를 반환하므로 에러 없이 안전하게 처리됩니다.
대안: Math.min / Math.max 활용
배열의 크기가 크지 않다면 전개 연산자(spread operator)와 Math 객체를 사용하는 더 간결한 방법도 있습니다.
const arr = [56, 34, 23, 687, 2, 56, 567]; const findMinMax = (arr = []) => [Math.min(...arr), Math.max(...arr)]; console.log(findMinMax(arr)); // [2, 687]
단, 이 방법은 전개 연산자가 모든 요소를 함수 인수로 전달하기 때문에 배열의 길이가 매우 클 경우(수십만 개 이상) 호출 스택 한도 초과 오류가 발생할 수 있다는 점에 유의해야 합니다. 대용량 데이터에는 앞서 소개한 reduce() 기반 접근 방식이 더 적합합니다.