행렬 테두리 회전하기
Level 2
문제 설명
rows x columns 크기인 행렬이 있습니다. 행렬에는 1부터 rows x columns까지의 숫자가 한 줄씩 순서대로 적혀있습니다. 이 행렬에서 직사각형 모양의 범위를 여러 번 선택해, 테두리 부분에 있는 숫자들을 시계방향으로 회전시키려 합니다. 각 회전은 (x1, y1, x2, y2)인 정수 4개로 표현하며, 그 의미는 다음과 같습니다.
- x1 행 y1 열부터 x2 행 y2 열까지의 영역에 해당하는 직사각형에서 테두리에 있는 숫자들을 한 칸씩 시계방향으로 회전합니다.
다음은 6 x 6 크기 행렬의 예시입니다.
이 행렬에 (2, 2, 5, 4) 회전을 적용하면, 아래 그림과 같이 2행 2열부터 5행 4열까지 영역의 테두리가 시계방향으로 회전합니다. 이때, 중앙의 15와 21이 있는 영역은 회전하지 않는 것을 주의하세요.
행렬의 세로 길이(행 개수) rows, 가로 길이(열 개수) columns, 그리고 회전들의 목록 queries가 주어질 때, 각 회전들을 배열에 적용한 뒤, 그 회전에 의해 위치가 바뀐 숫자들 중 가장 작은 숫자들을 순서대로 배열에 담아 return 하도록 solution 함수를 완성해주세요.
Logic
이 문제 역시 구현 문제같다. 예상치 못한 테스트 케이스는 없었으며 문제만 제대로 읽고 끈기만 있으면 풀 수 있다. 처음에 회전 그림만 보고 규칙이 있나 시간을 들였는데, 문제를 다시 읽으니 회전 기준 좌표 값을 제공한다. 문제를 꼼꼼히 읽자. 2차원 배열을 초기화하는 부분이 가장 중요하지 않았을까 생각한다. 나머지는 상하좌우 행렬을 업데이트하여 min 값을 구하면 된다.
Tip
- 파이썬 2차원 배열 0으로 초기화하기 ( 컬럼 수로 먼저 1차원 배열 만들고 2차원 행을 만들자. )
# columns : 가로 길이, rows : 세로 길이
board = [[0 for i in range(1, columns + 1)] for j in range(1, rows + 1)]
- 파이썬 2차원 배열 접근하기
for i in range(len(board)):
for j in range(len(board[i])):
board[i][j] = x
Code
def solution(rows, columns, queries):
answer = []
# 행렬 초기화 (columns : 가로 길이, rows : 세로 길이)
board = [[0 for i in range(1, columns + 1)] for j in range(1, rows + 1)]
x = 1
for i in range(len(board)):
for j in range(len(board[i])):
board[i][j] = x
x += 1
# 행렬 업데이트
for i in range(len(queries)):
changed_list = []
y1 = queries[i][0] - 1
x1 = queries[i][1] - 1
y2 = queries[i][2] - 1
x2 = queries[i][3] - 1
left_top = board[y1][x1]
right_top = board[y1][x2]
left_bottom = board[y2][x1]
right_bottom = board[y2][x2]
changed_list.append(left_top)
changed_list.append(right_top)
changed_list.append(left_bottom)
changed_list.append(right_bottom)
for x in range(x2, x1, -1): # x1+1,y1 ~ x2-1,y1 +1x 이동
board[y1][x] = board[y1][x-1]
changed_list.append(board[y1][x])
for x in range(x1, x2): # x2,y2 ~ x1+1,y2 -1x 이동
board[y2][x] = board[y2][x+1]
changed_list.append(board[y2][x])
for y in range(y1, y2-1):# x1,y1+1 ~ x1,y2 -1y 이동
board[y][x1] = board[y+1][x1]
changed_list.append(board[y][x1])
for y in range(y2, y1+1, -1): # x2,y1+1 ~ x2,y2 +1y 이동
board[y][x2] = board[y-1][x2]
changed_list.append(board[y][x2])
board[y1+1][x2] = right_top
board[y2][x2-1] = right_bottom
board[y2-1][x1] = left_bottom
answer.append(min(changed_list))
return answer
좋아요를 9개 받은 다른 사람 Code
def solution(rows, columns, queries):
answer = []
board = [[i+(j)*columns for i in range(1,columns+1)] for j in range(rows)]
# print(board)
for a,b,c,d in queries:
stack = []
r1, c1, r2, c2 = a-1, b-1, c-1, d-1
for i in range(c1, c2+1):
stack.append(board[r1][i])
if len(stack) == 1:
continue
else:
board[r1][i] = stack[-2]
for j in range(r1+1, r2+1):
stack.append(board[j][i])
board[j][i] = stack[-2]
for k in range(c2-1, c1-1, -1):
stack.append(board[j][k])
board[j][k] = stack[-2]
for l in range(r2-1, r1-1, -1):
stack.append(board[l][k])
board[l][k] = stack[-2]
answer.append(min(stack))
return answer
큰 틀은 비슷해보인다. 여기서 참고할 점은 반복문이다. 그리고 스택을 사용해서 멋지게 회전을 시켰다. 이야~
- 반복문 사용
for a,b,c,d in queries:
stack = []
r1, c1, r2, c2 = a-1, b-1, c-1, d-1
print(a, b, c, d)
print(r1, c1, r2, c2)
- 스택 사용
1. 현재 원소를 스택에 넣는다.
2. 현재 원소 자리에 스택의 끝에서 두번째 있는 원소(현재 원소 앞에 있던 아이)를 넣는다.
'Algorithm > Practice' 카테고리의 다른 글
2021 Dev-Matching: 웹 백엔드 개발(상반기) #3 (0) | 2021.09.08 |
---|---|
2021 Dev-Matching: 웹 백엔드 개발(상반기) #1 (0) | 2021.09.08 |
[프로그래머스] 단어 변환 (0) | 2021.04.19 |
프로그래머스 - 기능개발 (Python) (0) | 2021.04.08 |
프로그래머스 - 주식가격 (Python) (0) | 2021.03.30 |