행렬 테두리 회전하기 문제를 풀면서 배열 회전 문제에서 꼭 생각해야 하는 포인트를 다음과 같이 정리한다.
1) 회전 방향 선택에 따른 값 할당
배열을 시계방향으로 이동시킨다면 맨 처음 시작 위치 값을 TMP에 저장해 놓고 반시계방향으로 돌면서 시계방향으로 한 칸씩 값을 땡겨주어야 함, 반시계방향으로 이동시키면 반대임. 값을 이동시키는 방향과 내가 값을 초기화해주기 위해 이동하는 방향은 반대가 됨.
2) 처음 값 TMP 저장 후 마지막에 할당
처음 이동을 시작하는 위치의 값은 TMP에 저장하고, 마지막 위치에 도달했을 때 TMP 값을 넣어주어야 완성이 됨. 이 로직을 까먹었음.
3) 방향을 꺾는 위치가 고정되어 있고, 알려져 있다면 굳이 조건문을 사용할 필요가 없음
이 문제와 같은 경우 (X1,Y1), (X2,Y1), (X1,Y2), (X2, Y2)에서 방향을 꺾어주면 되므로 달팽이 문제처럼 범위를 벗어나거나 이미 방문한 곳이면 꺾는다와 같은 조건문을 지정해주는 것도 좋지만 하드코딩 방식으로 좌표를 설정해주는 것도 좋음. 그렇게 하면 현재 dir 값으로 이동했을 때 다음 좌표 값을 계산하여 조건문에 걸리면 dir을 바꾸고 다시 다음 좌표를 조정해주는 로직을 없앨 수 있음. 아래는 내가 푼 풀이인데 이 부분을 고려하여 코드 개선이 가능함.
import java.util.*;
class Solution {
public int[] solution(int rows, int columns, int[][] queries) {
int[] answer = new int[queries.length];
int[][] arr = new int[rows+1][columns+1];
int num = 1;
for(int i=1; i<rows+1; i++){
for(int j=1; j<columns+1; j++){
arr[i][j] = num++;
}
}
int[] dx = {1,0,-1,0};
int[] dy = {0,1,0,-1};
for(int i=0; i<queries.length; i++){
int x1 = queries[i][0];
int y1 = queries[i][1];
int x2 = queries[i][2];
int y2 = queries[i][3];
int tmp = arr[x1][y1];
int d = 0;
Queue<int[]> q = new LinkedList<>();
q.offer(new int[] {x1,y1});
int min = Integer.MAX_VALUE;
while(true) {
int[] cur = q.poll();
int x = cur[0];
int y = cur[1];
if(arr[x][y] < min) {
min = arr[x][y];
answer[i] = min;
}
int nx = x + dx[d];
int ny = y + dy[d];
if(nx>x2 || ny >y2 || nx < x1 || ny < y1) d++;
nx = x + dx[d];
ny = y + dy[d];
if(nx == x1 && ny == y1){
arr[x][y] = tmp;
break;
}
arr[x][y] = arr[nx][ny];
q.offer(new int[] {nx, ny});
}
}
return answer;
}
}