📝 문제
rows x columns 크기인 행렬이 있습니다. 행렬에는 1부터 rows x columns까지의 숫자가 한 줄씩 순서대로 적혀있습니다. 이 행렬에서 직사각형 모양의 범위를 여러 번 선택해, 테두리 부분에 있는 숫자들을 시계방향으로 회전시키려 합니다. 각 회전은 (x1, y1, x2, y2)인 정수 4개로 표현하며, 그 의미는 다음과 같습니다.
- x1 행 y1 열부터 x2 행 y2 열까지의 영역에 해당하는 직사각형에서 테두리에 있는 숫자들을 한 칸씩 시계방향으로 회전합니다.
다음은 6 x 6 크기 행렬의 예시입니다.
🔑 나의 풀이
function solution(rows, columns, queries) {
let answer = [];
let board = Array.from({length: rows+1}, () => new Array(columns+1));
for(let i = 1; i <= rows; i ++) {
for(let j = 1; j <= columns; j++) {
board[i][j] = ((i-1) * columns + j);
}
}
queries.forEach(query => {
let [fromR,fromC,toR,toC] = query;
let r = fromR;
let c = fromC;
let cur = board[r][c];
let next = 0;
let min = rows * columns
// 상단 (왼 -> 오)
for(let i = fromC; i < toC; i++) {
if(min > cur) min = cur;
next = board[r][++c];
board[r][c] = cur;
cur = next;
}
// 우측 (위 -> 아래)
for(let i = fromR; i < toR; i++) {
if(min > cur) min = cur;
next = board[r++][c];
board[r][c] = cur;
cur = next;
}
// 아래쪽 (오 -> 왼)
for(let i = fromC; i < toC; i++) {
if(min > cur) min = cur;
next = board[r][--c];
board[r][c] = cur;
cur = next;
}
// 왼쪽 (아래 -> 위)
for(let i = fromR; i < toR; i++) {
if(min > cur) min = cur;
next = board[--r][c];
board[r][c] = cur;
cur = next;
}
answer.push(min);
})
return answer;
}
풀이 설명
function solution(rows, columns, queries) {
let answer = [];
let board = Array.from({length: rows+1}, () => new Array(columns+1)); // 행렬의 틀 만들기
for(let i = 1; i <= rows; i ++) { // 행렬 채우기
for(let j = 1; j <= columns; j++) {
board[i][j] = ((i-1) * columns + j);
}
}
// queries의 요소 순회 // ex) [2,2,5,4]
queries.forEach(query => {
let [fromR,fromC,toR,toC] = query;
let r = fromR; // 출발 위치
let c = fromC;
let cur = board[r][c]; // 옮길 값 저장
let next = 0; // 다음으로 옮길 값 저장
let min = rows * columns // 최소값 저장할 변수
// 상단 (왼 -> 오)
for(let i = fromC; i < toC; i++) {
if(min > cur) min = cur; // cur이 더 작으면 저장
next = board[r][++c]; // 해당 값 next에 저장
board[r][c] = cur; // 그 자리에 cur 넣기
cur = next; // cur이 next값이 됨
}
// 우측 (위 -> 아래)
for(let i = fromR; i < toR; i++) {
if(min > cur) min = cur;
next = board[++r][c];
board[r][c] = cur;
cur = next;
}
// 아래쪽 (오 -> 왼)
for(let i = fromC; i < toC; i++) {
if(min > cur) min = cur;
next = board[r][--c];
board[r][c] = cur;
cur = next;
}
// 왼쪽 (아래 -> 위)
for(let i = fromR; i < toR; i++) {
if(min > cur) min = cur;
next = board[--r][c];
board[r][c] = cur;
cur = next;
}
answer.push(min); // 순회를 마쳤으니 min은 회전한 수 중 최소값임
})
return answer;
}
초기 행렬을 만들지 않고 변경하는 값만 저장하려고 했는데 그게 더 복잡해져서 그냥 만들고 했다.
다른 풀이를 보니 큐를 이용해서 일단 값을 뺀 다음, 회전하고 다시 집어넣는 방법도 있던데,
난 그냥 회전하는 그대로 구현하고 그 과정에서 최소값이랑 비교해주는 방법을 택했다.
까다롭지는 않았으나 은근히 복잡했던 문제
주의할 점은 주어진 ((i-1) x columns + j) 식의 i행과 j열은 1부터 시작한다.
그러므로 행렬을 (rows + 1) x (columns + 1) 크기만큼 만들고 채워야 계산이 쉽다.
실제로는 rows x columns 만큼의 행렬만 채워지지만, 답을 구하는 데는 상관없다.
초기 행렬을 만들고 -> 보기에 따라 회전해서 각 값에 저장 -> 회전하는 값 중 최소값 저장 -> answer 반환
- 정확도 테스트 결과
'Coding test' 카테고리의 다른 글
[Leetcode] 1689. Partitioning Into Minimum Number Of Deci-Binary Numbers - javascript (0) | 2022.07.06 |
---|---|
[Leetcode] Array101(explore) 풀이 모음 - javascript (0) | 2022.07.05 |
[프로그래머스] 거리두기 확인하기 (Lv 2) - javascript (0) | 2022.06.29 |
[프로그래머스] 수식 최대화 (Lv 2) - javascript (0) | 2022.06.28 |
[프로그래머스] 튜플 (Lv 2) - javascript (0) | 2022.06.28 |