숫자 배열을 입력받아, 그중 단 한 번만 등장하는 고유한(unique) 요소들의 합을 반환하는 JavaScript 함수를 작성해야 합니다. 즉, 배열 안에 두 번 이상 나타나는 중복 숫자들은 합산에서 제외하고, 오직 한 번씩만 존재하는 값들만 더하는 것이 핵심입니다.
문제 이해하기
예를 들어 다음과 같은 입력 배열이 주어졌다고 가정해 보겠습니다.
const arr = [2, 5, 5, 3, 2, 7, 4, 9, 9, 11];
이 배열에서 5, 2, 9는 각각 두 번씩 등장하므로 고유한 요소가 아닙니다. 반면 3, 7, 4, 11은 한 번씩만 나타나므로 고유한 요소입니다.
따라서 결과는 다음과 같습니다.
3 + 7 + 4 + 11 = 25
해결 접근 방식
가장 직관적인 방법은 for 루프를 사용해 배열을 순회하면서 각 요소가 배열 내에서 유일한지 확인하는 것입니다. 특정 요소가 처음 등장한 인덱스(indexOf)와 마지막으로 등장한 인덱스(lastIndexOf)가 같다면, 그 요소는 배열에 단 한 번만 존재한다는 의미입니다. 두 값이 다르다면 중복된 요소이므로 건너뛰면 됩니다.
구현 코드
위 로직을 코드로 구현하면 다음과 같습니다.
const arr = [2, 5, 5, 3, 2, 7, 4, 9, 9, 11];
const sumUnique = arr => {
let res = 0;
for(let i = 0; i < arr.length; i++){
// indexOf와 lastIndexOf가 다르면 중복 요소이므로 건너뜀
if(arr.indexOf(arr[i]) !== arr.lastIndexOf(arr[i])){
continue;
};
res += arr[i];
};
return res;
};
console.log(sumUnique(arr));실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 출력이 표시됩니다.
25
추가 팁: filter 메서드 활용하기
for 루프 대신 filter()와 reduce()를 조합하면 더 간결하게 작성할 수도 있습니다.
const sumUnique = arr =>
arr.filter(num => arr.indexOf(num) === arr.lastIndexOf(num))
.reduce((sum, num) => sum + num, 0);
console.log(sumUnique([2, 5, 5, 3, 2, 7, 4, 9, 9, 11])); // 25두 방법 모두 시간 복잡도는 O(n²)로 동일하지만, 함수형 스타일을 선호한다면 두 번째 방법이 가독성 면에서 유리할 수 있습니다. 배열의 크기가 매우 큰 경우에는 Map 객체를 사용해 각 숫자의 등장 횟수를 먼저 세는 O(n) 방식을 고려해 보는 것도 좋습니다.