https://school.programmers.co.kr/learn/courses/30/lessons/77485
2차원 배열의 일부분을 회전하는 로직을 직접 구현해야하는 문제입니다.
아이디어를 떠올리는 부분은 어렵지 않으나 직접 구현하는데 있어 어려움이 있을 수 있습니다.
대략적인 구현 순서는 아래와 같습니다.
queries
를 순회하며, 시계 방향 회전 로직을 1에서 생성한 2차원 배열에 적용한다.queries
에 대한 순회가 1회 끝날 때마다 3에서 만든 최소힙에서 가장 작은 숫자를 꺼내 정답 배열에 저장한다.먼저 1에 대한 구현입니다.
int[][] board = new int[rows][columns];
int n = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
board[i][j] = n++;
}
}
다음은 2 ~ 4에 대한 구현입니다.
회전을 적용하는 과정에서 직접 board
를 수정할 경우 회전이 적용된 위치에 덮어써지는 값을 찾을 수 없으므로 board
를 카피한 copyBoard
를 이용합니다.
그리고 각 회전 단계에서 필요한 값은 회전 경로에 있는 값들 중 가장 작은 값이므로 최소힙을 만들고 활용합니다.
for (int k = 0; k < queries.length; k++) {
int[][] copyBoard = new int[rows][columns];
for (int i = 0; i < rows; i++) {
System.arraycopy(board[i], 0, copyBoard[i], 0, columns);
}
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
int[] query = queries[k];
int x1 = query[1] - 1;
int x2 = query[3] - 1;
int y1 = query[0] - 1;
int y2 = query[2] - 1;
for (int i = y1; i <= y2; i++) {
for (int j = x1; j <= x2; j++) {
if (i > y1 && i < y2 && j > x1 && j < x2)
continue;
minHeap.add(board[i][j]);
// x+1 rotate
if (i == y1 && j < x2) {
copyBoard[i][j + 1] = board[i][j];
}
// y+1 rotate
else if (i != y2 && j == x2) {
copyBoard[i + 1][j] = board[i][j];
}
// x-1 rotate
else if (i == y2 && j != x1) {
copyBoard[i][j - 1] = board[i][j];
}
// y-1 rotate
else {
copyBoard[i - 1][j] = board[i][j];
}
}
}
Integer minNum = minHeap.peek();
if (minNum != null) {
answers[k] = minNum;
}
board = copyBoard;
}
마지막으로 전체 구현부에 대한 코드입니다.
import java.util.*;
class Solution {
public int[] solution(int rows, int columns, int[][] queries) {
int[] answers = new int[queries.length];
int[][] board = new int[rows][columns];
int n = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
board[i][j] = n++;
}
}
for (int k = 0; k < queries.length; k++) {
int[][] copyBoard = new int[rows][columns];
for (int i = 0; i < rows; i++) {
System.arraycopy(board[i], 0, copyBoard[i], 0, columns);
}
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
int[] query = queries[k];
int x1 = query[1] - 1;
int x2 = query[3] - 1;
int y1 = query[0] - 1;
int y2 = query[2] - 1;
for (int i = y1; i <= y2; i++) {
for (int j = x1; j <= x2; j++) {
if (i > y1 && i < y2 && j > x1 && j < x2)
continue;
minHeap.add(board[i][j]);
// x+1 rotate
if (i == y1 && j < x2) {
copyBoard[i][j + 1] = board[i][j];
}
// y+1 rotate
else if (i != y2 && j == x2) {
copyBoard[i + 1][j] = board[i][j];
}
// x-1 rotate
else if (i == y2 && j != x1) {
copyBoard[i][j - 1] = board[i][j];
}
// y-1 rotate
else {
copyBoard[i - 1][j] = board[i][j];
}
}
}
Integer minNum = minHeap.peek();
if (minNum != null) {
answers[k] = minNum;
}
board = copyBoard;
}
return answers;
}
}
시간 복잡도의 경우, queries
의 길이 q
x n
x m
(n
, m
은 열과 행의 크기) = O(qnm)이 됩니다.
공간 복잡도의 경우 n
x m
2차원 배열의 크기인 O(nm)이 됩니다.