n × n 크기의 정사각 행렬(배열의 배열)을 입력받아 시계 방향으로 90도 회전시키는 JavaScript 함수를 작성해야 합니다. 여기서 중요한 조건은 추가 배열을 새로 할당하지 않고 제자리(in-place)에서 수행해야 한다는 점입니다.
문제 이해하기
예를 들어, 입력 배열이 다음과 같다고 가정해 보겠습니다.
const arr = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ];
이 배열을 시계 방향으로 90도 회전하면 결과는 다음과 같아야 합니다.
const output = [ [7, 4, 1], [8, 5, 2], [9, 6, 3], ];
즉, 첫 번째 열이 아래에서 위로 읽히면서 첫 번째 행이 되는 형태로 요소들의 위치가 바뀝니다.
접근 방법: 전치 후 행 반전
제자리 회전은 별도의 배열 없이 다음 두 단계만으로 깔끔하게 해결할 수 있습니다.
1단계 — 전치(Transpose): 행과 열을 서로 교환합니다. 즉, arr[i][j]와 arr[j][i]의 값을 맞바꿉니다. 대각선 기준으로 위쪽 삼각형 영역만 순회하면 중복 스왑을 피할 수 있습니다.
2단계 — 각 행 좌우 반전: 전치된 행렬의 각 행을 왼쪽 끝과 오른쪽 끝부터 안쪽으로 맞바꾸며 뒤집습니다.
이 두 연산을 순서대로 적용하면 시계 방향 90도 회전과 동일한 결과가 되며, 공간 복잡도는 O(1), 시간 복잡도는 O(n²)입니다.
구현 코드
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
const rotateArray = (arr = []) => {
// 1단계: 행렬 전치 (행과 열 교환)
for (let rowIndex = 0; rowIndex < arr.length; rowIndex += 1) {
for (let columnIndex = rowIndex + 1; columnIndex < arr.length;
columnIndex += 1) {
[
arr[columnIndex][rowIndex],
arr[rowIndex][columnIndex],
] = [
arr[rowIndex][columnIndex],
arr[columnIndex][rowIndex],
];
}
}
// 2단계: 각 행을 좌우로 반전
for (let rowIndex = 0; rowIndex < arr.length; rowIndex += 1) {
for (let columnIndex = 0; columnIndex < arr.length / 2;
columnIndex += 1) {
[
arr[rowIndex][arr.length - columnIndex - 1],
arr[rowIndex][columnIndex],
] = [
arr[rowIndex][columnIndex],
arr[rowIndex][arr.length - columnIndex - 1],
];
}
}
};
rotateArray(arr);
console.log(arr);실행 결과
위 코드를 콘솔에서 실행하면 다음과 같은 출력을 확인할 수 있습니다.
[ [ 7, 4, 1 ], [ 8, 5, 2 ], [ 9, 6, 3 ] ]
정리
이 알고리즘의 핵심은 전치 → 행 반전이라는 두 단계 분할입니다. ES6의 배열 구조 분해 할당(Destructuring Assignment)을 활용하면 임시 변수 없이도 값을 손쉽게 맞바꿀 수 있어 코드가 더욱 간결해집니다. 같은 원리를 응용하면 반시계 방향 회전은 행 반전 → 전치 순서로 구현할 수 있습니다.