문제 정의
배열과 숫자 n을 인수로 받는 JavaScript 함수를 작성해야 합니다. 이 함수는 배열을 n개의 요소만큼 회전시켜야 하며, 즉 앞쪽에 있는 n개의 요소를 잘라내어 배열의 맨 뒤로 옮기는 작업을 수행합니다.
여기서 중요한 조건이 하나 있습니다. 바로 추가적인 메모리 공간을 사용하지 않고, 새로운 배열을 만들지 않은 채 기존 배열 자체(in-place)에서 작업을 처리해야 한다는 점입니다.
입력 및 출력 예시
입력 배열이 다음과 같다고 가정해 보겠습니다.
const arr = [12, 6, 43, 5, 7, 2, 5];
회전 횟수 n이 3이라면, 앞의 세 요소(12, 6, 43)가 맨 뒤로 이동하므로 출력은 다음과 같아야 합니다.
const output = [5, 7, 2, 5, 12, 6, 43];
구현 코드
다음은 위 문제를 해결하는 전체 코드입니다.
const arr = [12, 6, 43, 5, 7, 2, 5];
const num = 5;
// 배열을 왼쪽으로 한 칸씩 이동시키는 함수
const rotateByOne = arr => {
for(let i = 0; i < arr.length - 1; i++){
let temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
// Array 프로토타입에 rotateBy 메서드 추가
Array.prototype.rotateBy = function(n){
const { length: l } = this;
// n이 배열 길이보다 크거나 같으면 원본 그대로 유지
if(n >= l){
return;
}
for(let i = 0; i < n; i++){
rotateByOne(this);
}
};
arr.rotateBy(num);
console.log(arr);
코드 설명
rotateByOne 함수: 인접한 두 요소를 서로 교환(swap)하면서 배열 전체를 왼쪽으로 한 칸씩 이동시킵니다. 이 과정에서 첫 번째 요소가 자연스럽게 마지막 위치로 밀려나게 됩니다.
rotateBy 메서드: Array 객체의 프로토타입에 직접 추가한 커스텀 메서드로, 모든 배열 인스턴스에서 호출할 수 있습니다. 내부적으로 rotateByOne을 n번 반복 호출하여 원하는 만큼 회전을 수행합니다.
만약 n이 배열 길이보다 크거나 같다면 배열이 한 바퀴 이상 돌게 되어 결국 원본과 동일한 상태가 됩니다. 따라서 불필요한 연산을 피하기 위해 아무 작업 없이 종료하도록 처리했습니다.
이 방식은 별도의 임시 배열을 생성하지 않고 변수 하나(temp)만 사용해 요소를 교환하므로 O(1)의 추가 공간만 필요합니다. 대신 회전 한 번당 배열 전체를 순회하기 때문에 시간 복잡도는 O(n × k)가 됩니다(k는 회전 횟수). 더 빠른 성능이 필요하다면 요소 교환 방식이나 반전(reversal) 알고리즘을 활용해 O(n)으로 최적화할 수도 있습니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다. 이 예제에서는 num이 5이므로 앞의 다섯 요소(12, 6, 43, 5, 7)가 뒤로 이동합니다.
[
2, 5, 12, 6,
43, 5, 7
]