문제 개요
최소 하나 이상의 모음을 포함하는 문자열이 주어졌을 때, 문자열의 각 문자마다 가장 가까운 모음까지의 거리를 숫자로 매핑한 배열을 반환하는 JavaScript 함수를 작성해야 합니다.
예를 들어, 입력 문자열이 다음과 같다면 −
const str = 'vatghvf';
출력 결과는 다음과 같아야 합니다.
const output = [1, 0, 1, 2, 3, 4, 5];
여기서 두 번째 문자 'a'는 그 자체가 모음이므로 거리가 0이고, 첫 번째 문자 'v'는 인덱스 1에 있는 'a'까지의 거리가 1입니다. 나머지 문자들도 마찬가지 방식으로 계산됩니다.
해결 코드
다음은 위 문제를 해결하는 전체 코드입니다 −
const str = 'vatghvf';
const nearest = (arr = [], el) => arr.reduce((acc, val) => Math.min(acc,
Math.abs(val - el)), Infinity);
const vowelNearestDistance = (str = '') => {
const s = str.toLowerCase();
const vowelIndex = [];
for(let i = 0; i < s.length; i++){
if(s[i] === 'a' || s[i] === 'e' || s[i] === 'i' || s[i] === 'o' ||
s[i] === 'u'){
vowelIndex.push(i);
};
};
return s.split('').map((el, ind) => nearest(vowelIndex, ind));
};
console.log(vowelNearestDistance(str));코드 설명
이 코드의 동작 과정을 단계별로 살펴보겠습니다.
1단계: 소문자 변환 및 모음 인덱스 수집
먼저 toLowerCase() 메서드로 문자열을 모두 소문자로 변환하여 대소문자 구분 없이 처리할 수 있도록 합니다. 그다음 반복문을 돌며 'a', 'e', 'i', 'o', 'u'에 해당하는 문자의 인덱스를 vowelIndex 배열에 저장합니다.
2단계: 각 문자별 최소 거리 계산
nearest 헬퍼 함수는 reduce()를 사용하여 주어진 인덱스와 모든 모음 인덱스 사이의 절댓값 차이 중 가장 작은 값을 찾습니다. 초기값으로 Infinity를 설정하면 어떤 거리보다 큰 값에서 비교를 시작할 수 있습니다.
3단계: 결과 매핑
마지막으로 split('')으로 문자열을 문자 배열로 만든 뒤, map()을 통해 각 문자의 인덱스에 대해 가장 가까운 모음까지의 거리를 계산한 새로운 배열을 반환합니다.
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다 −
[ 1, 0, 1, 2, 3, 4, 5 ]
결과를 보면 'v'(인덱스 0)는 'a'(인덱스 1)까지 거리가 1, 'a'(인덱스 1)는 자신이 모음이므로 0, 't'(인덱스 2)는 'a'까지 거리가 1, 이후 문자들은 왼쪽의 'a'가 가장 가까우므로 각각 2, 3, 4, 5가 됩니다.
시간 복잡도 참고
위 방식은 각 문자마다 모든 모음 인덱스를 확인하므로 시간 복잡도가 O(n × m)(n은 문자열 길이, m은 모음 개수)입니다. 더 효율적인 접근이 필요하다면 양방향 스캔(two-pass scan) 기법을 활용해 O(n)으로 최적화할 수 있습니다. 즉, 왼쪽에서 오른쪽으로 한 번, 오른쪽에서 왼쪽으로 한 번 스캔하면서 각 위치에서 가장 가까운 모음까지의 거리를 갱신하는 방식입니다.