import java.util.ArrayDeque;
import java.util.Deque;
public class Solution {
// 행렬과 연산
// Deque 자료구조에서
// add(A) + peek(B) or remove(B)가 있을 때 // (A)와 (B)는 First 또는 Last
// (A)와 (B)가 같다면 스택(Stack)처럼 동작
// (A)와 (B)가 다르다면 큐(Queue)처럼 동작
// addFirst로 쌓고 있는 구조에서 제일 앞에 원소를 추가하고 싶다면 addLast로 추가
// addLast로 쌓고 있는 구조에서 제일 앞에 원소를 추가하고 싶다면 addFirst로 추가
static int r = 0; // rc의 행 수
static int c = 0; // rc의 열 수
static Deque<Integer> firstCol; // rc의 1열
static Deque<Integer> lastCol; // rc의 마지막열
static Deque<Deque<Integer>> restRows; // rc의 1열, 마지막열을 제외한 나머지 행들
// 2차원 배열을 2개의 열과 나머지 행 구조로 나누기
public static void rcSetting(int[][] rc) {
r = rc.length; // 행
c = rc[0].length; // 열
firstCol = new ArrayDeque<Integer>(); // 1열
lastCol = new ArrayDeque<Integer>(); // 마지막열
restRows = new ArrayDeque<Deque<Integer>>(); // 나머지 행
// 1 2 3
// 4 5 6
// 7 8 9
// 2차원 배열이 위와 같다면
// r = 3, c = 3
// firstCol = {1, 4, 7}
// lastCol = {3, 6, 9}
// restRows = {2, 5, 8}
// 상단, 좌측부터 addFirst로 넣을 거야
// 모두 addFirst로 넣는다는 것을 기억
for (int i = 0; i < r; i++) {
firstCol.addFirst(rc[i][0]); // 1열 담기
lastCol.addFirst(rc[i][c - 1]); // 마지막열 담기
Deque<Integer> tempRow = new ArrayDeque<Integer>(); // restRows에 담을 tempRow 생성
for (int j = 1; j < c - 1; j++) { // 1열과 마지막열을 제외한 모든 열의 원소 담기
tempRow.addFirst(rc[i][j]);
}
restRows.addFirst(tempRow); // tempRow 담기
}
}
// 테두리 한 칸씩 시계방향 회전
public static void rotate() {
if (c == 2) { // firstCol, lastCol만으로 이루어진 2차원 배열
lastCol.addLast(firstCol.removeLast());
// firstCol의 제일 처음에 들어왔던 원소가 빠져나가야 함 => addFirst에서 Queue 구조로 빠져나가려면 removeLast로 빼내야 한다.
// 빼낸 값을 lastCol의 addFirst로 제일 처음 들어왔던 원소보다 앞에 넣어야 하므로 addLast로 넣어준다.
firstCol.addFirst(lastCol.removeFirst());
// lastCol의 제일 마지막에 들어왔던 원소가 빠져나가야 함 => addFirst에서 Stack 구조로 빠져나가려면 removeFirst로 빼내야 한다.
// 빼낸 값을 firstCol의 addFirst로 가장 마지막에 들어왔던 원소의 뒤에 넣어야 하므로 똑같이 addFirst로 넣어준다.
return;
}
// 테두리에 원소 추가할 순서는 상, 우, 하, 좌 순서로 하겠다.
restRows.peekLast().addLast(firstCol.removeLast()); // 1열(firstCol)의 처음 들어온 원소를 빼냄(addFirst에서 Queue 구조로 쓰기 위해 removeLast) => restRows의 처음 들어온 행을 기준으로 잡아야 함(Queue 구조로 쓰기 위해 peekLast) => 행의 원소 중 처음에 들어왔던 원소보다 앞에 넣어줘야 하므로 addLast
lastCol.addLast(restRows.peekLast().removeFirst()); // restRows의 처음 들어온 행 중 마지막 원소를 빼내어 마지막 열 제일 앞에 끼어들기해서 추가
restRows.peekFirst().addFirst(lastCol.removeFirst()); // 마지막 열의 제일 마지막에 들어온 원소를 빼내어 restRows의 가장 마지막에 들어온 행 중 가장 마지막에 들어온 원소 뒤에 추가
firstCol.addFirst(restRows.peekFirst().removeLast()); // restRows의 가장 마지막에 들어온 행 중 처음 들어온 원소를 빼내어 1열 제일 마지막에 들어온 원소 뒤에 추가
}
// 행 한 칸씩 아래로 이동
public static void shiftRow() {
// 가장 마지막에 들어온 행 또는 원소를 가장 처음 위치에 넣어줘야 한다. addFirst 추가 구조이므로 스택 구조로 빼내기 위해 removeFirst, 제일 앞에 추가해줘야 하므로 addLast를 써준다.
restRows.addLast(restRows.removeFirst()); // 행
firstCol.addLast(firstCol.removeFirst()); // 1열
lastCol.addLast(lastCol.removeFirst()); // 마지막열
}
public static int[][] solution(int[][] rc, String[] operations) {
int[][] answer = {};
// STEP 1. 2차원 배열 rc => 2개의 열과 나머지 행 구조로 나누기
rcSetting(rc);
// STEP 2. 메인 작업
for (String operation : operations) { // "Rotate", "ShiftRow"
switch (operation.charAt(0)) { // 'R', 'S'
case 'R' : rotate(); break;
case 'S' : shiftRow(); break;
}
}
// STEP 3. 2차원 배열 answer에 값 담기
answer = new int[r][c];
for (int i = 0; i < r; i++) {
// addFirst 추가 구조에서 큐 구조로 빼내기 위해 removeLast 사용
answer[i][0] = firstCol.removeLast(); // 1열
answer[i][c - 1] = lastCol.removeLast(); // 마지막열
Deque<Integer> tempRow = new ArrayDeque<Integer>(); // restRows의 각 행을 담기 위해 tempRow 생성
// addFirst 추가 구조에서 큐 구조로 빼내기 위해 removeLast 사용
tempRow = restRows.removeLast();
for (int j = 1; j < c - 1; j++) {
answer[i][j] = tempRow.removeLast();
}
}
return answer;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] rc = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
String[] operations = {"Rotate", "ShiftRow"}; // Rotate : 행렬 바깥쪽에 있는 원소를 시계 방향으로 회전, ShiftRow : 행을 한 칸씩 아래로 이동
// Rotate ShiftRow
// 1 2 3 4 1 2 8 9 6
// 4 5 6 7 5 3 4 1 2
// 7 8 9 8 9 6 7 5 9
System.out.println(solution(rc, operations)); // {{8, 9, 6}, {4, 1, 2}, {7, 5, 3}}
}
}
Deque 자료구조에 대해 어느 정도 학습이 된 후 풀이하는 것을 추천한다.
프로그래머스 행렬과 연산 문제 풀이 Java
'Java > 프로그래머스' 카테고리의 다른 글
[Java] 프로그래머스 [Level-2] 올바른 괄호 (0) | 2022.11.28 |
---|---|
[Java] 프로그래머스 [Level-2] 구명보트 (0) | 2022.11.27 |
[Java] 프로그래머스 [Level-2] 두 큐 합 같게 만들기 (0) | 2022.11.27 |
[Java] 프로그래머스 [Level-1] 성격 유형 검사하기 (0) | 2022.11.27 |
[Java] 프로그래머스 [Level-4] 도둑질 (0) | 2022.11.27 |