JavaScript에서 간단한 함수를 작성해야 한다고 가정해 보겠습니다. 이 함수는 숫자로만 이루어진 배열(어떤 깊이로든 중첩될 수 있음)을 인수로 받아, 그 안에 존재하는 가장 큰 숫자를 반환해야 합니다.
문제 정의
예를 들어, 입력 배열이 다음과 같다면 −
const arr = [
34, 65, 67,
[
43, 76, 87, 23, 56, 7,
[
54, 7, 87, 23, 79, 994, 2
],
54
], 54, 4, 2
];
함수는 값이 배열의 어느 위치에 있든 상관없이 최댓값인 다음 값을 반환해야 합니다 −
994
접근 방식: 재귀 활용
배열의 중첩 깊이가 사전에 정해져 있지 않기 때문에 단순한 반복문만으로는 모든 경우를 처리하기 어렵습니다. 따라서 재귀(recursion)를 사용하는 것이 가장 자연스러운 해결책입니다. 핵심 아이디어는 다음과 같습니다.
- 배열의 각 요소를 순회하면서 해당 요소가 배열인지 확인합니다.
- 요소가 배열이라면, 그 하위 배열에 대해 같은 함수를 재귀적으로 호출합니다.
- 요소가 숫자라면, 현재까지의 최댓값과 비교하여 필요할 때 갱신합니다.
예제 코드
이를 구현한 코드는 다음과 같습니다 −
const arr = [
34, 65, 67,
[
43, 76, 87, 23, 56, 7,
[
54, 7, 87, 23, 79, 994, 2
],
54
], 54, 4, 2
];
const getGreatest = (arr, greatest = -Infinity) => {
for(let i = 0; i < arr.length; i++){
// 요소가 배열이면 재귀 호출로 하위 배열 탐색
if(Array.isArray(arr[i])){
greatest = getGreatest(arr[i], greatest);
} else if(arr[i] > greatest){
greatest = arr[i]; // 더 큰 숫자 발견 시 갱신
}
}
return greatest;
};
console.log(getGreatest(arr));
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다 −
994
코드 동작 원리
위 코드의 흐름을 단계별로 살펴보겠습니다.
- 기본값 설정: 매개변수
greatest의 기본값을-Infinity로 지정하여, 어떤 숫자와 비교해도 항상 작은 값에서 시작하도록 합니다. - 배열 판별:
Array.isArray()메서드로 현재 요소가 배열인지 검사합니다. - 재귀 호출: 요소가 배열이라면 같은 함수를 다시 호출해 하위 배열을 탐색하고, 그 결과를
greatest에 반영합니다. - 최댓값 갱신: 요소가 일반 숫자라면 현재 최댓값보다 클 때만 값을 교체합니다.
- 결과 반환: 모든 요소의 순회가 끝나면 최종 최댓값을 반환합니다.
주의할 점은, 재귀 호출 시 곧바로 return해 버리면 현재 배열의 나머지 요소들을 건너뛰게 된다는 것입니다. 위 코드처럼 재귀 호출의 결과를 greatest 변수에 할당하는 방식으로 처리하면, 임의의 깊이와 순서를 가진 중첩 배열에서도 항상 정확한 최댓값을 얻을 수 있습니다.