프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
행렬의 특정 영역 테두리를 시계 방향으로 회전시키고, 그 과정에서 이동한 숫자들 중 최솟값을 찾는 문제입니다. collections.deque 자료구조를 활용한 효율적인 회전과 실시간 최솟값 추적을 적용했습니다.
1. 나의 풀이 (Modular Approach)
기능별로 함수를 분리하고, deque를 도입하여 회전 로직의 가독성과 성능을 높였습니다. 한 줄이 길어질 수 있는 연산은 코드 블록으로 나누어 작성했습니다.
from collections import deque
def rotate(board, point):
# 0-인덱스 보정
row1, col1 = point[0] - 1, point[1] - 1
row2, col2 = point[2] - 1, point[3] - 1
# 변의 길이 계산
horizontal_len = abs(col2 - col1 + 1)
vertical_len = abs(row2 - row1 + 1)
# 최솟값 초기화 및 추출을 위한 변수 설정
min_val = board[row1][col1]
r, c = row1, col1 - 1
deq = deque()
# 1. 테두리 값 추출 및 실시간 최솟값 갱신
for _ in range(horizontal_len):
c += 1
deq.append(board[r][c])
if board[r][c] < min_val:
min_val = board[r][c]
for _ in range(vertical_len - 1):
r += 1
deq.append(board[r][c])
if board[r][c] < min_val:
min_val = board[r][c]
for _ in range(horizontal_len - 1):
c -= 1
deq.append(board[r][c])
if board[r][c] < min_val:
min_val = board[r][c]
for _ in range(vertical_len - 2):
r -= 1
deq.append(board[r][c])
if board[r][c] < min_val:
min_val = board[r][c]
# 2. 데큐를 이용한 시계 방향 1칸 회전
deq.rotate(1)
# 3. 회전된 값을 다시 보드에 삽입
r, c = row1, col1 - 1
index = 0
for _ in range(horizontal_len):
c += 1
board[r][c] = deq[index]
index += 1
for _ in range(vertical_len - 1):
r += 1
board[r][c] = deq[index]
index += 1
for _ in range(horizontal_len - 1):
c -= 1
board[r][c] = deq[index]
index += 1
for _ in range(vertical_len - 2):
r -= 1
board[r][c] = deq[index]
index += 1
return min_val
def solution(rows, columns, queries):
answer = []
# 보드 초기화
board = [[0] * columns for _ in range(rows)]
counter = 1
for i in range(rows):
for j in range(columns):
board[i][j] = counter
counter += 1
# 쿼리 순차 수행
for query in queries:
answer.append(rotate(board, query))
return answer
2. 오늘 배운 점 및 복기 노트
collections.deque의 rotate() 활용
리스트 슬라이싱을 이용한 회전(arr[-1:] + arr[:-1])보다 deque.rotate(1)을 사용하는 것이 자료구조의 목적에 부합하며 가독성이 훨씬 뛰어납니다. 내부적으로 양방향 연결 리스트 형태를 띠어 양 끝단의 데이터 조작에 최적화되어 있습니다.
실시간 최솟값 추적 최적화
이전에는 추출이 끝난 뒤 min(arr)을 호출했으나, 데이터를 하나씩 추출하여 데큐에 넣는 루프 안에서 즉시 최솟값을 비교 및 갱신하도록 수정했습니다. 이를 통해 별도의 순회 비용을 줄일 수 있습니다.
좌표 보정과 루프 제어
사각형 테두리를 돌 때 모서리 부분이 중복으로 들어가지 않도록 horizontal_len, vertical_len - 1, horizontal_len - 1, vertical_len - 2 순으로 루프 범위를 설계하는 디테일한 인덱스 제어 방식을 익혔습니다.
3. 프로그래머스 코딩 테스트 문제 풀이 전략 교재에서 배울만한 점
리스트 컴프리헨션을 이용한 Pythonic 초기화
중첩 for문 대신 행과 열의 인덱스 규칙을 활용한 리스트 컴프리헨션으로 보드를 초기화하는 방식이 간결하고 성능면에서도 유리합니다.
board = [[(i * columns + j + 1) for j in range(columns)] for i in range(rows)]
인플레이스(In-place) 스왑을 통한 공간 최적화
별도의 리스트나 데큐를 생성하지 않고, temp 변수 하나만 사용하여 보드 내에서 직접 값을 당겨오는 방식의 효율성을 배웠습니다. 공간 복잡도를 $O(1)$로 유지해야 하는 상황에서 필수적이지만, 실수할 가능성이 있으니 전략에 따라 deque를 사용하는 저의 방식도 나쁘지 않겠네요.
시계 방향 회전의 반시계 방향 순회
시계 방향으로 값을 한 칸씩 밀기 위해, 실제 코드 루프는 반대 방향(반시계)으로 돌며 앞의 값을 현재 위치로 가져오는 방식이 데이터 덮어쓰기 문제를 깔끔하게 해결한다는 인사이트를 얻었습니다.
'알고리즘 > 프로그래머스' 카테고리의 다른 글
| 문제1 - 교점에 별 만들기 (Python) (0) | 2026.04.20 |
|---|
