문제 소개
정수 배열 arr(중복 값을 포함할 수 있음)를 첫 번째 인자로, 숫자 num을 두 번째 인자로 받는 JavaScript 함수를 작성해야 합니다.
함수의 역할은 배열을 순회하면서 어떤 숫자가 num번보다 많이 등장하는지 확인하는 것입니다. 만약 그러한 요소가 존재한다면, 초과되는 등장 횟수를 삭제하여 해당 요소가 최대 num번까지만 나타나도록 제한해야 합니다.
입력 예시
const arr = [4, 1, 3, 1, 4, 1, 3, 4, 2];
const num = 2;
출력
const output = [4, 1, 3, 1, 4, 3, 2];
출력 설명
숫자 4와 1은 각각 세 번 등장했기 때문에, 세 번째로 등장한 값이 삭제되었습니다. 그 결과 모든 요소가 최대 2번까지만 나타나는 배열이 반환됩니다.
접근 방법
이 문제는 해시 객체(맵)를 활용하면 효율적으로 해결할 수 있습니다. 핵심 아이디어는 다음과 같습니다.
1. 결과를 담을 새로운 배열과 각 요소의 등장 횟수를 기록할 객체를 준비합니다.
2. 원본 배열을 한 번씩 순회하면서 현재 요소의 등장 횟수를 1씩 증가시킵니다.
3. 등장 횟수가 num 이하일 때만 결과 배열에 요소를 추가합니다.
4. num이 0인 경우에는 어떤 요소도 포함될 수 없으므로 빈 배열을 바로 반환합니다.
이 방식은 배열을 한 번만 순회하므로 시간 복잡도는 O(n)입니다.
구현 코드
다음은 위 로직을 구현한 전체 코드입니다.
const arr = [4, 1, 3, 1, 4, 1, 3, 4, 2];
const num = 2;
const deleteExtra = (arr = [], num = 1) => {
if(num === 0){
return [];
};
const res = [];
const map = {};
for(let i = 0; i < arr.length; i++){
const el = arr[i];
map[el] = (map[el] || 0) + 1;
if(map[el] <= num){
res.push(el);
};
};
return res;
};
console.log(deleteExtra(arr, num));
실행 결과
[ 4, 1, 3, 1, 4, 3, 2 ]
코드 설명
map[el] = (map[el] || 0) + 1; 구문은 해당 요소가 처음 등장했을 때는 undefined가 되므로 이를 0으로 처리한 뒤 1을 더하는 방식입니다. 덕분에 별도의 초기화 과정 없이 등장 횟수를 손쉽게 누적할 수 있습니다.
또한 map[el] <= num 조건 검사를 통해 등장 횟수가 허용 범위를 넘지 않는 경우에만 결과 배열에 요소를 추가합니다. 이 조건 덕분에 원래 배열의 순서는 그대로 유지되면서, 각 요소의 앞부분 등장만 남기고 뒤에 오는 중복 값들은 자연스럽게 제거됩니다.