숫자 배열을 유일한 입력값으로 받는 JavaScript 함수를 작성해야 합니다. 이때 입력 배열에는 중복된 숫자가 포함되어 있을 수 있습니다.
작성할 함수는 배열을 오름차순으로 정렬한 뒤, 동일한(중복된) 숫자들을 각각 별도의 하위 배열로 묶어서 반환해야 합니다.
문제 예시
입력 배열이 다음과 같다고 가정해 보겠습니다.
const arr = [5, 7, 5, 7, 8, 9, 1, 1];
그렇다면 기대하는 출력 결과는 다음과 같습니다.
const output = [ [1, 1], [5, 5], [7, 7], [8], [9] ];
출력 결과를 보면 같은 숫자끼리 하나의 하위 배열에 모여 있고, 각 하위 배열은 오름차순으로 정렬되어 있는 것을 확인할 수 있습니다.
구현 코드
이 문제는 아래와 같이 해결할 수 있습니다.
const arr = [5, 7, 5, 7, 8, 9, 1, 1];
const sortAndGroup = (arr = []) => {
let result = [];
let groupArray;
// 숫자 크기 기준으로 오름차순 정렬
arr.sort((a, b) => a - b);
for (let i = 0; i < arr.length; i++) {
// 이전 요소와 값이 다르면 새로운 그룹 생성
if (arr[i - 1] !== arr[i]) {
groupArray = [];
result.push(groupArray);
}
// 현재 요소를 현재 그룹에 추가
groupArray.push(arr[i]);
}
return result;
};
console.log(sortAndGroup(arr));코드 동작 원리
이 알고리즘의 핵심 로직은 다음과 같습니다.
1단계 — 정렬: arr.sort((a, b) => a - b)를 사용해 배열을 오름차순으로 정렬합니다. JavaScript의 기본 sort()는 문자열 기준으로 비교하기 때문에, 숫자 배열을 정렬할 때는 반드시 비교 함수를 전달해야 올바른 결과를 얻을 수 있습니다.
2단계 — 그룹 경계 판별: 배열을 순회하면서 현재 요소 arr[i]와 바로 앞의 요소 arr[i - 1]을 비교합니다. 두 값이 다르다는 것은 새로운 숫자 그룹이 시작된다는 의미이므로, 빈 배열을 만들어 결과 배열에 추가합니다.
3단계 — 그룹에 요소 추가: 현재 요소를 활성화된 그룹 배열(groupArray)에 계속 push하면, 같은 값들이 자연스럽게 하나의 하위 배열에 모이게 됩니다.
정렬된 배열에서는 동일한 값이 항상 인접해 있기 때문에, 이 방식으로 한 번의 순회만으로 모든 중복 숫자를 효율적으로 그룹화할 수 있습니다. 시간 복잡도는 정렬에 의해 지배되며 O(n log n)입니다.
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ [ 1, 1 ], [ 5, 5 ], [ 7, 7 ], [ 8 ], [ 9 ] ]
기대했던 대로 중복된 숫자들이 각각 별도의 하위 배열로 잘 그룹화된 것을 확인할 수 있습니다.