오랜만에 제 글 봤는데 저도 이해 안되길래 수정했습니다 (24.08.28)
계기
- 코딩 테스트 준비를 하다보면, 2차원 배열 전체 혹은 일부를 회전하는 문제가 등장함
- 반시계 방향, 시계 방향을 즉석에서 구현하기 힘드니 암기를 해야 함
- 때론 회전한 후의 좌표를 명확히 알아야 해서 다음 좌표가 어떻게 생겼는지 구할 줄 알아야 함
- 시험장에서도 기억날 수 있는 방법이 필요해
암기하면 위험할 수도 있는 공식들
A = list(map(list, zip(*arr[::-1])))
- 이렇게 한 줄로 된 공식은 암기하기 편하긴 함
- 하지만 행렬 전체가 아니라 행렬 일부만 회전하는 문제들이 등장함
- 응용할 줄 알겠다면 상관 없으나 나처럼 for 문으로 외우는 게 안전할 것 같으면 읽어보자
직관적으로 암기 말고 이해부터 하기
1. 시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동
시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동
- 못 믿겠다고? 예시로 보자
[원본]
1 2 3
4 5 6
[대각선 대칭 이동]
1 4
2 5
3 6
[좌우 대칭 이동]
4 1
5 2
6 3
- 결론적으로 시계 방향 90도 회전이 되었다.
- 만약 좌우 대칭이 아니라 상하 대칭 이동하면 어떨까?
2. 반시계 방향 90도 회전 = 대각선 대칭 이동 + 상하 대칭 이동
[원본]
1 2 3
4 5 6
[대각선 대칭 이동]
1 4
2 5
3 6
[상하 대칭 이동]
3 6
2 5
1 4
- 반시계 90도 회전이 되었다
코드로 구현해보기
# r = num_of_row, c = num_of_c
arr = [
[1, 2, 3],
[4, 5, 6]
]
r, c = len(arr), len(arr[0])
- 우선 예제를 2 X 3 인 2차원 배열을 만들었다
- 내 공식은 '가장 왼쪽이면서 가장 위쪽인 좌표'를 [0][0]으로 규정할 때 적용가능함
- 참고로 arr[x][y] 로 값에 접근한다
- 예컨대, arr[0][1] = 2, arr[1][2] = 6 이다
- 즉, arr[x][y] 로 하기로 했으니 x가 세로를 담당하고 y 가 가로를 담당한다
- r은 row, c는 column을 의미함
1. 대각선 대칭 이동
new_x = old_y
new_y = old_x
- 일단 원본에서 대각선을 기준으로 뒤집어보자
for i in range(r):
for j in range(c):
new_arr[j][i] = old_arr[i][j]
- for 문으로 구현하는 이렇게 된다. 어렵지 않다.
2. 좌우 대칭 이동
new_x = old_x
new_y = (r - 1) - old_y
- y 가 가로라고 위에서 말했음. 그러므로 y값에 변화를 줘야 좌우대칭이 됨.
- r: 행렬의 가로 길이 (일단 행렬 전체를 회전한다고 가정)
for i in range(r):
for j in range(c):
new_arr[i][(r - 1) - j] = old_arr[i][j]
- for문은 이렇게 생겼을 듯
3. 시계 방향 90도 회전 = 대각선 대칭 이동 + 좌우 대칭 이동
# 시계방향 90도 회전
new_x = old_y
new_y = (r - 1) - old_x
- 대각선 대칭 이동 후에 좌우 대칭 공식 합하면 이렇게 됨
for i in range(r):
for j in range(i + 1, c):
new_arr[j][(r - 1) - i] = old_arr[i][j]
시험장에서 어떻게 해야 하나
- 기억 안 나면, '대각선 대칭 이동' + '머시기 이동'만 기억한다
- '머시기 이동'이 좌우가 시계인지, 반시계인지 헷갈리면 위처럼 작은 행렬 그려서 확인해본다
더 잘 하고 싶다면
- 어려운 문제는 전체 배열이 아닌 일부만 잘라서 이동시키기 때문에 주의해야 한다
- 특히 위 공식은 (0,0)이 좌측 상단 꼭짓점일 때 가능하므로, 아닌 경우엔 대칭 이동시켜야 한다
(0, 0)이 아닌 경우: 대칭 이동 예제
# sx, sy: 회전해야 할 영역의 좌측 상단 꼭짓점
for i in range(sx, sx + r):
for j in range(sy, sy + c):
ox, oy = i - sx, j - sy # (0, 0) 으로 이동
nx, ny = oy, (r - 1) - ox # 시계 방향 90도 이동
new_arr[nx + sx][ny + sy] = old_arr[i][j]