배열 arr과 숫자 n이 주어졌을 때, 모든 요소가 최대 n번까지만 반복되도록 배열을 정리하는 함수를 작성해야 합니다. 여기서 중요한 조건은 원하는 요소들의 상대적인 순서를 유지한 채, 제자리에서(in-place) 배열을 직접 수정해야 한다는 점입니다.
문제 해결 접근 방식
핵심 아이디어는 객체(해시맵)를 활용해 각 요소의 등장 횟수를 추적하는 것입니다. 배열을 순회하는 도중 특정 요소의 등장 횟수가 허용된 최대치 n에 도달하면, splice() 메서드로 해당 요소를 제거합니다.
splice(i, 1)로 요소를 삭제하면 뒤에 있던 요소들이 한 칸씩 앞으로 당겨집니다. 따라서 루프 변수 i를 1 감소(i--)시켜 다음 반복에서 요소를 건너뛰지 않도록 보정해야 합니다. 이 인덱스 보정 과정이 제자리 배열 수정에서 가장 흔히 실수하기 쉬운 부분입니다.
예제 코드
const arr = [7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35,
35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41,
35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7,
2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10];
const array = [12, 4, 2, 12, 32, 21, 67, 4, 32, 5];
const deleteExtra = (arr, n) => {
const map = {};
for(let i = 0; i < arr.length; i++){
if(map[arr[i]]){
if(map[arr[i]] >= n){
arr.splice(i, 1);
i--;
}else{
map[arr[i]]++;
}
continue;
};
map[arr[i]] = 1;
}
};
deleteExtra(array, 1);
deleteExtra(arr, 2);
console.log(array);
console.log(arr);실행 결과
콘솔에는 다음과 같이 출력됩니다.
[ 12, 4, 2, 32, 21, 67, 5 ] [ 7, 26, 21, 41, 43, 2, 26, 24, 10, 10, 24, 35, 35, 43, 41, 7, 21, 2, 28 ]
첫 번째 배열은 각 요소가 한 번씩만 남도록 중복이 모두 제거된 결과이며, 두 번째 배열은 각 요소가 최대 두 번까지 나타나도록 정리된 결과입니다. 두 경우 모두 기존 요소들의 상대적인 순서는 그대로 유지됩니다.