문제 개요
JavaScript에서 다음과 같은 함수를 작성해야 합니다.
이 함수는 첫 번째 인수로 숫자 배열을, 두 번째 인수로 허용할 최대 등장 횟수를 나타내는 숫자를 받습니다.
함수는 배열에서 요소들을 삭제하여, 결과 배열에 어떤 요소도 두 번째 인수로 지정된 횟수보다 많이 나타나지 않도록 만들어야 합니다.
예시
예를 들어 아래와 같은 입력이 주어졌다고 가정해 보겠습니다.
const arr = [4, 2, 3, 2, 4, 2, 2, 4];
const num = 2;
위 입력의 경우 각 숫자는 최대 2번까지만 남아 있어야 하므로, 기대하는 출력 결과는 다음과 같습니다.
[ 2, 2, 3, 4, 4 ]
코드 구현
이 문제는 객체(Object)를 활용해 각 숫자의 등장 횟수를 추적하는 방식으로 해결할 수 있습니다. 전체 코드는 다음과 같습니다.
const arr = [4, 2, 3, 2, 4, 2, 2, 4];
const num = 2;
const deleteExcess = (arr = [], num = 1) => {
const map = {};
for(let i = 0; i < arr.length; i++){
if(!map[arr[i]]){
map[arr[i]] = 1;
}else if(map[arr[i]] + 1 <= num){
map[arr[i]]++
};
};
const res = [];
Object.keys(map).forEach(key => {
for(i = 0; i < map[key]; i++){
res.push(key);
};
});
return res.map(Number);
};
console.log(deleteExcess(arr, num));
동작 원리
이 코드의 로직을 단계별로 살펴보면 다음과 같습니다.
1단계 — 등장 횟수 집계: 빈 객체 map을 생성하고, 배열을 순회하며 각 숫자가 처음 등장하면 해당 키의 값을 1로 설정합니다. 이미 존재하는 숫자라면, 현재 횟수에 1을 더한 값이 허용 횟수 num 이하일 때만 카운트를 증가시킵니다. 이 조건 덕분에 num을 초과하는 등장은 자동으로 무시됩니다.
2단계 — 결과 배열 생성: Object.keys()로 객체의 모든 키(숫자)를 가져온 뒤, 각 키의 값(남길 횟수)만큼 반복하여 새로운 배열 res에 요소를 추가합니다.
3단계 — 타입 변환: 객체의 키는 문자열이므로, 마지막에 map(Number)를 사용해 결과 배열의 요소들을 다시 숫자 타입으로 변환합니다.
출력 결과
[ 2, 2, 3, 4, 4 ]
실행 결과를 보면 원래 4번 등장했던 숫자 2는 2번만 남고, 3번 등장했던 숫자 4 역시 2번만 유지된 것을 확인할 수 있습니다. 이처럼 객체 기반의 카운팅 방식을 활용하면 시간 복잡도 O(n)으로 효율적으로 문제를 해결할 수 있습니다.