import java.util.*;

public class Solution {
	
	// 등산코스 정하기
	
	public static int INF = 10000001;
	public static HashMap<Integer, ArrayList<Node>> nodeListMap = new HashMap<>();
	public static HashMap<Integer, Integer> maxOfMinIntensityMap = new HashMap<>();
	public static int totalNum = 0;
	public static int[] arrGates = {};
	public static int[] arrSummits = {};
	
	public static int dijkstra(int i, int j) {
		PriorityQueue<Node> pq = new PriorityQueue<>();
		Node pqNode;
		ArrayList<Node> nodeList;
		
		int summit = arrSummits[i];
		int gate = arrGates[j];
		
		boolean[] targetNode = new boolean[totalNum + 1]; // 1개의 출입구, 1개의 봉우리만 지나도록 boolean 배열
		
		Arrays.fill(targetNode, true);
		
		for (int k = 0; k < arrSummits.length; k++) {
			
			if (arrSummits[k] == summit) {
				continue;
			}
			
			targetNode[arrSummits[k]] = false;
		}
		
		for (int k = 0; k < arrGates.length; k++) {
			
			if (arrGates[k] == gate) {
				continue;
			}
			
			targetNode[arrGates[k]] = false;
		}
		
		for (int key : nodeListMap.keySet()) {
			maxOfMinIntensityMap.put(key, INF); // 최소 Intensity 코스 중 최대 Intensity 값 무한대로 초기화
		}
		
		maxOfMinIntensityMap.put(summit, 0); // 출발 봉우리의 Intensity값 0
		
		pq.add(new Node(summit, 0));
		
		while (!pq.isEmpty()) {
			pqNode = pq.poll();
			
			if (pqNode.getIntensity() > maxOfMinIntensityMap.get(pqNode.getIndex())) {
				continue;
			}
			
			nodeList = nodeListMap.get(pqNode.getIndex());
			
			for (Node node : nodeList) {
				
				if (!targetNode[node.getIndex()]) {
					continue; // 지정된 봉우리, 출입구가 아닐 경우 경유 불가
				}
				
				if (pqNode.getIntensity() + node.getIntensity() < maxOfMinIntensityMap.get(node.getIndex())) {
					maxOfMinIntensityMap.put(node.getIndex(), Math.max(pqNode.getIntensity(), node.getIntensity()));
					pq.add(new Node(node.getIndex(), Math.max(pqNode.getIntensity(), node.getIntensity())));
				}
			}
		}
		
		int minIntensity = maxOfMinIntensityMap.get(arrGates[0]);
		
		for (int n = 1; n < arrGates.length; n++) {
			
			if (maxOfMinIntensityMap.get(arrGates[n]) < minIntensity) {
				minIntensity = maxOfMinIntensityMap.get(arrGates[n]);
			}
		}
		
		return minIntensity;
	}
	
	public static int[] solution(int n, int[][] paths, int[] gates, int[] summits) {
		int[] answer = {};
		int MinSummit = 0;
		int MinIntensity = INF;
        
		totalNum = n;
		arrGates = Arrays.copyOf(gates, gates.length);
		arrSummits = Arrays.copyOf(summits, summits.length);
        		
		for (int i = 0; i < n + 1; i++) {
			nodeListMap.put(i, new ArrayList<Node>());
		}
        
		for (int i = 0; i < paths.length; i++) {
			nodeListMap.get(paths[i][0]).add(new Node(paths[i][1], paths[i][2]));
			nodeListMap.get(paths[i][1]).add(new Node(paths[i][0], paths[i][2]));
		}
        
		Arrays.sort(arrSummits); // intensity값 같을 경우 봉우리 번호 작은 것이 대상이 되도록 정렬 & 답 구할 때 더 작은 intensity값이 있을 경우에만 갱신되도록
        
		int tempIntensity = 0;
        
		for (int i = 0; i < arrSummits.length; i++) {
        	
			for (int j = 0; j < arrGates.length; j++) {
        		
				tempIntensity = dijkstra(i, j);
        		
				if (tempIntensity < MinIntensity) {
					MinIntensity = tempIntensity;
					MinSummit = arrSummits[i];
				}
			}
		}
        
		answer = new int[2];
        
		answer[0] = MinSummit;
		answer[1] = MinIntensity;
        
		System.out.println(MinSummit + " " + MinIntensity);
        
		return answer;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n = 7;
		int[][] paths = {{1, 2, 5}, {1, 4, 1}, {2, 3, 1}, {2, 6, 7}, {4, 5, 1}, {5, 6, 1}, {6, 7, 1}};
		int[] gates = {3, 7};
		int[] summits = {1, 5};
		
		// gates 중 하나의 번호만 선택 가능하며, 제일 처음과 마지막이어야 함 => 3 - ... - 3
		// summits 중 하나만 선택 가능하며, intensity를 최소로 만들 수 있는 번호 => 1과 5중 하나만 들어가야 함
		// ex) 출입구 7, 봉우리 5를 선택했다면 : 7 - (1) - 6 - (1) - 5 - (1) - 6 - (1) - 7 (intensity는 1)
		// 거쳤던 길의 크기 중 최대 값이 intensity가 된다. 우리는 그 intensity가 최소가 되는 출입구와 봉우리를 찾아야 한다.
		// 7 - (1) - 6 - (7) - 2 - (7) - 6 - (1) - 5 - (1) - 6 - (1) - 7
		// 다른 루트를 거친다고 해서 필수로 거치는 출입구 ~ 봉우리까지의 intensity를 낮출 수는 없다.
		// 즉, 출입구(A) - 길(B) - 봉우리(C) - 길(B) - 출입구(A)와 같이, 갔던 길로 되돌아오는 루트만 생각하면 된다는 의미이다.
		// 예를 들면
		// 출입구 3, 봉우리 1 : 3-2-1-2-3 => 3-2-1 또는 1-2-3만 봐도 됨
		// 출입구 3, 봉우리 5 : 3-2-6-5-6-2-3 => 3-2-6-5 또는 5-6-2-3만 봐도 됨
		// 출입구 7, 봉우리 1 : 7-6-2-1-2-6-7 => 7-6-2-1 또는 1-2-6-7만 봐도 됨
		// 출입구 7, 봉우리 5 : 7-6-5-6-7 => 7-6-5 또는 5-6-7만 봐도 됨
		// 이 문제에서는 봉우리 번호와 intensity 최소값을 원하므로, 봉우리에서 출발 -> 출입구 도착 루트로 문제를 풀겠다.
		
		System.out.println(solution(n, paths, gates, summits)); // {5, 1} // {봉우리 번호, intensity 최소값}
	}
}
public class Node implements Comparable<Node> {
	
	private int index = 0; // 등산코스 번호
	private int intensity = 0; // 등산코스 시간
	
	public Node(int index, int intensity) {
		this.index = index;
		this.intensity = intensity;
	}
	
	public int getIndex() {
		return this.index;
	}
	
	public int getIntensity() {
		return this.intensity;
	}

	@Override
	public int compareTo(Node otherNode) {
		// TODO Auto-generated method stub
		return this.intensity - otherNode.intensity; // intensity 기준 오름차순 정렬
	}
}

우선순위 큐를 활용하여 다익스트라 알고리즘으로 문제를 해결하고자 했으나

아직 시간 초과 존재

 

프로그래머스 등산코스 정하기 문제 풀이 Java 소스 코드

STEP 1. SUBMISSION_DATE와 ID, NM의 출력은 간단하다.

SELECT MST.SUBMISSION_DATE
     , (SELECT HACKER_ID
          FROM SUBMISSIONS
         WHERE SUBMISSION_DATE = MST.SUBMISSION_DATE
      GROUP BY HACKER_ID
      ORDER BY COUNT(SUBMISSION_ID) DESC, HACKER_ID LIMIT 1) AS ID
     , (SELECT NAME
          FROM HACKERS
         WHERE HACKER_ID = ID) AS NM
  FROM (SELECT DISTINCT SUBMISSION_DATE FROM SUBMISSIONS) MST
 GROUP BY MST.SUBMISSION_DATE

STEP 2. 아래 쿼리를 이해하자

SELECT COUNT(DISTINCT HACKER_ID)  
  FROM SUBMISSIONS S2  
 WHERE S2.SUBMISSION_DATE = '2016-03-03'
   AND (SELECT COUNT(DISTINCT S3.SUBMISSION_DATE) 
          FROM SUBMISSIONS S3 
         WHERE S3.HACKER_ID = S2.HACKER_ID 
           AND S3.SUBMISSION_DATE < '2016-03-03') = DATEDIFF('2016-03-03', '2016-03-01')

STEP 3. 두 개의 쿼리문을 합치면

SELECT MST.SUBMISSION_DATE
     , (SELECT COUNT(DISTINCT HACKER_ID)  
          FROM SUBMISSIONS S2  
         WHERE S2.SUBMISSION_DATE = MST.SUBMISSION_DATE
           AND (SELECT COUNT(DISTINCT S3.SUBMISSION_DATE) 
                  FROM SUBMISSIONS S3 
                 WHERE S3.HACKER_ID = S2.HACKER_ID 
                   AND S3.SUBMISSION_DATE < MST.SUBMISSION_DATE) = DATEDIFF(MST.SUBMISSION_DATE, '2016-03-01')) AS CNT
     , (SELECT HACKER_ID
          FROM SUBMISSIONS
         WHERE SUBMISSION_DATE = MST.SUBMISSION_DATE
      GROUP BY HACKER_ID
      ORDER BY COUNT(SUBMISSION_ID) DESC, HACKER_ID LIMIT 1) AS ID
     , (SELECT NAME
          FROM HACKERS
         WHERE HACKER_ID = ID) AS NM
  FROM (SELECT DISTINCT SUBMISSION_DATE FROM SUBMISSIONS) MST
 GROUP BY MST.SUBMISSION_DATE

해커랭크 15 Days of Learning SQL

우선순위 큐를 활용한 풀이

import java.util.ArrayList;
import java.util.HashMap;
import java.util.PriorityQueue;

public class DijkstraByPriorityQueue {
	
	public static int n = 6; // 노드의 개수
	public static int INF = 1000000; // 무한대를 의미
	public static HashMap<Integer, ArrayList<Node>> nodeListMap = new HashMap<>(); // key : 각 노드의 인덱스(0 ~ 5), value : 각 노드의 인덱스로부터 전체 노드까지의 인덱스와 거리를 담을 리스트
	public static HashMap<Integer, Integer> minDistanceMap = new HashMap<>(); // key : 각 노드의 인덱스(0 ~ 5), value : 각 노드까지의 최단거리(출발 노드로부터)
	
	public static void dijkstra(int start) {
		PriorityQueue<Node> pq = new PriorityQueue<>(); // 우선순위 큐 생성 // 출발 노드로부터 현재 최단거리에 있는 노드부터 우선적으로 빼내어 체크하기 위함(출발 노드로부터 현재 최단거리에 있는 노드를 체크해야 다른 노드들까지의 최단거리 갱신의 가능성이 있기 때문)
		Node pqNode; // 우선순위 큐에서 빼낸 노드를 담을 변수(출발 노드로부터 현재 최단거리에 있는 노드)
		ArrayList<Node> nodeList; // 우선순위 큐에서 빼낸 (출발 노드로부터 현재 최단거리)노드를 거쳐서 체크할 타겟 노드 리스트

		// 각 노드까지의 최단거리 초기화
		for (int key : nodeListMap.keySet()){ // 0 ~ 5
			minDistanceMap.put(key, INF); // 모든 최단거리 무한대로 초기화
		}
        
		minDistanceMap.put(start, 0); //출발 노드까지의 최단거리는 0으로 SET
        
		pq.add(new Node(start, 0)); // 출발 노드를 우선순위 큐에 추가 // 최단거리가 갱신되었으므로 우선순위 큐에 추가 => 이 최단거리를 거쳐 다른 노드들까지의 최단거리도 갱신될 수 있기 때문

		while (!pq.isEmpty()) { // 더 이상 최단거리 갱신이 불가할 때까지 반복

			pqNode = pq.poll(); // 출발 노드로부터 현재 최단거리에 있는 노드

			if (pqNode.getDistance() > minDistanceMap.get(pqNode.getIndex())) { // 최단거리 갱신이 가능한지 체크
				continue;
			}
            
			nodeList = nodeListMap.get(pqNode.getIndex()); // 현재 최단거리에 있는 노드를 거쳐서 체크할 타겟 노드 리스트
            
			for (Node node : nodeList) { // 타겟 노드 0 ~ 5 모두 체크
                
				if (pqNode.getDistance() + node.getDistance() < minDistanceMap.get(node.getIndex())) { // 출발 노드로부터 현재 최단거리에 있는 노드를 거쳐서 타겟 노드로 가는 거리가 타겟 노드의 최단거리보다 작을 경우
					minDistanceMap.put(node.getIndex(), pqNode.getDistance() + node.getDistance()); // 타겟 노드의 최단거리 갱신
					pq.add(new Node(node.getIndex(), pqNode.getDistance() + node.getDistance())); // 타겟 노드 우선순위 큐에 추가
				}
			}
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for (int i = 0; i < n; i++) { // 0 ~ 5
			nodeListMap.put(i, new ArrayList<Node>()); // key값 0 ~ 5(각 노드 인덱스)마다 Node 정보를 담을 리스트 생성
		}
		
		nodeListMap.get(0).add(new Node(0, 0)); // 0번 노드로부터 0번 노드까지의 거리 0
		nodeListMap.get(0).add(new Node(1, 2)); // 0번 노드로부터 1번 노드까지의 거리 2
		nodeListMap.get(0).add(new Node(2, 5)); // 0번 노드로부터 2번 노드까지의 거리 5
		nodeListMap.get(0).add(new Node(3, 1)); // 0번 노드로부터 3번 노드까지의 거리 1
		nodeListMap.get(0).add(new Node(4, INF)); // 0번 노드로부터 4번 노드까지의 거리 INF
		nodeListMap.get(0).add(new Node(5, INF)); // 0번 노드로부터 5번 노드까지의 거리 INF
		
		nodeListMap.get(1).add(new Node(0, 2)); // 1번 노드로부터 0번 노드까지의 거리 2
		nodeListMap.get(1).add(new Node(1, 0)); // 1번 노드로부터 1번 노드까지의 거리 0
		nodeListMap.get(1).add(new Node(2, 3)); // 1번 노드로부터 2번 노드까지의 거리 3
		nodeListMap.get(1).add(new Node(3, 2)); // 1번 노드로부터 3번 노드까지의 거리 2
		nodeListMap.get(1).add(new Node(4, INF)); // 1번 노드로부터 4번 노드까지의 거리 INF
		nodeListMap.get(1).add(new Node(5, INF)); // 1번 노드로부터 5번 노드까지의 거리 INF
		
		nodeListMap.get(2).add(new Node(0, 5)); // 2번 노드로부터 0번 노드까지의 거리 5
		nodeListMap.get(2).add(new Node(1, 3)); // 2번 노드로부터 1번 노드까지의 거리 3
		nodeListMap.get(2).add(new Node(2, 0)); // 2번 노드로부터 2번 노드까지의 거리 0
		nodeListMap.get(2).add(new Node(3, 3)); // 2번 노드로부터 3번 노드까지의 거리 3
		nodeListMap.get(2).add(new Node(4, 1)); // 2번 노드로부터 4번 노드까지의 거리 1
		nodeListMap.get(2).add(new Node(5, 5)); // 2번 노드로부터 5번 노드까지의 거리 5
		
		nodeListMap.get(3).add(new Node(0, 1)); // 3번 노드로부터 0번 노드까지의 거리 1
		nodeListMap.get(3).add(new Node(1, 2)); // 3번 노드로부터 1번 노드까지의 거리 2
		nodeListMap.get(3).add(new Node(2, 3)); // 3번 노드로부터 2번 노드까지의 거리 3
		nodeListMap.get(3).add(new Node(3, 0)); // 3번 노드로부터 3번 노드까지의 거리 0
		nodeListMap.get(3).add(new Node(4, 1)); // 3번 노드로부터 4번 노드까지의 거리 1
		nodeListMap.get(3).add(new Node(5, INF)); // 3번 노드로부터 5번 노드까지의 거리 INF
		
		nodeListMap.get(4).add(new Node(0, INF)); // 4번 노드로부터 0번 노드까지의 거리 INF
		nodeListMap.get(4).add(new Node(1, INF)); // 4번 노드로부터 1번 노드까지의 거리 INF
		nodeListMap.get(4).add(new Node(2, 1)); // 4번 노드로부터 2번 노드까지의 거리 1
		nodeListMap.get(4).add(new Node(3, 1)); // 4번 노드로부터 3번 노드까지의 거리 1
		nodeListMap.get(4).add(new Node(4, 0)); // 4번 노드로부터 4번 노드까지의 거리 0
		nodeListMap.get(4).add(new Node(5, 2)); // 4번 노드로부터 5번 노드까지의 거리 2
		
		nodeListMap.get(5).add(new Node(0, INF)); // 5번 노드로부터 0번 노드까지의 거리 INF
		nodeListMap.get(5).add(new Node(1, INF)); // 5번 노드로부터 1번 노드까지의 거리 INF
		nodeListMap.get(5).add(new Node(2, 5)); // 5번 노드로부터 2번 노드까지의 거리 5
		nodeListMap.get(5).add(new Node(3, INF)); // 5번 노드로부터 3번 노드까지의 거리 INF
		nodeListMap.get(5).add(new Node(4, 2)); // 5번 노드로부터 4번 노드까지의 거리 2
		nodeListMap.get(5).add(new Node(5, 0)); // 5번 노드로부터 5번 노드까지의 거리 0
		
		dijkstra(0); // 출발 노드 0
		
		for (int i = 0; i < n; i++) { // 0 ~ 5
			System.out.print(minDistanceMap.get(i) + " "); // 각 노드까지의 최단거리 출력(출발 노드로부터)
		}
	}
}
public class Node implements Comparable<Node> {
	
	private int index = 0; // 노드의 번호
	private int distance = 0; // 노드의 거리
	
	public Node(int index, int distance) {
		this.index = index;
		this.distance = distance;
	}
	
	public int getIndex() {
		return this.index;
	}
	
	public int getDistance() {
		return this.distance;
	}

	@Override
	public int compareTo(Node otherNode) {
		// TODO Auto-generated method stub
		return this.distance - otherNode.distance; // distance 기준 오름차순 정렬 // 1, 2, 3, ...
//		return otherNode.distance - this.distance; // distance 기준 내림차순 정렬 // ..., 3, 2, 1
	}
}

 

출력 결과 : 0 2 3 1 2 4

 

Dijkstra(다익스트라) 알고리즘 우선순위 큐 문제 풀이 Java 소스 코드

<MySQL>

 

SQL_MODE 확인

SHOW VARIABLES LIKE 'SQL_MODE'

SQL_MODE 초기화

SET SQL_MODE = '';

 

'SQL > 참고자료' 카테고리의 다른 글

[SQL] @변수  (0) 2022.09.07
[SQL] ROW_NUMBER()  (0) 2022.08.31
[SQL] 대소문자 구분 없이 특정 문자열 포함하는 데이터 조회  (0) 2022.08.31
[SQL] 집계 함수를 조건으로 사용  (0) 2022.08.31
[SQL] 멀티 테이블  (0) 2022.08.31

SQL_MODE = ONLY_FULL_GROUP_BY 확인

(GROUP BY절에 포함되지 않은 컬럼을 집합함수로 감싸야만 사용할 수 있게 해줌)

 

SHOW VARIABLES LIKE 'SQL_MODE'

SQL_MODE를 확인해보자

SQL_MODE 초기화 & 조회

SET SQL_MODE = '';
SELECT A.START_DATE, B.END_DATE
  FROM (SELECT START_DATE FROM PROJECTS WHERE START_DATE NOT IN (SELECT END_DATE FROM PROJECTS)) A,
       (SELECT END_DATE FROM PROJECTS WHERE END_DATE NOT IN (SELECT START_DATE FROM PROJECTS)) B
 WHERE A.START_DATE < B.END_DATE
 GROUP BY A.START_DATE
 ORDER BY DATEDIFF(B.END_DATE, A.START_DATE), A.START_DATE

해커랭크 SQL Project Planning SQL

'SQL > 해커랭크' 카테고리의 다른 글

[SQL] 해커랭크 Ollivander's Inventory  (0) 2022.09.13
[SQL] 해커랭크 15 Days of Learning SQL  (0) 2022.09.09
[SQL] 해커랭크 Top Competitors  (0) 2022.09.06
[SQL] 해커랭크 The Report  (0) 2022.09.04
[SQL] 해커랭크 Occupations  (0) 2022.09.01

SET @변수명 = 초기값 (:= 가능)

 

SELECT @변수명

또는

SELECT @변수명 := @변수명 + 더해줄 값

등으로 사용 가능

SELECT T.HACKER_ID
     , T.NAME
  FROM (SELECT A.HACKER_ID
             , D.NAME
             , (CASE WHEN A.SCORE = C.SCORE THEN 'PASS' ELSE 'FAIL' END) AS RESULT
          FROM SUBMISSIONS A, CHALLENGES B, DIFFICULTY C, HACKERS D
         WHERE A.CHALLENGE_ID = B.CHALLENGE_ID
           AND A.HACKER_ID = D.HACKER_ID
           AND B.DIFFICULTY_LEVEL = C.DIFFICULTY_LEVEL
      ORDER BY A.HACKER_ID) T
 WHERE T.RESULT = 'PASS'
 GROUP BY T.HACKER_ID, T.NAME
HAVING COUNT(T.RESULT) > 1
 ORDER BY COUNT(T.RESULT) DESC, T.HACKER_ID

RESULT 값의 집계함수를 조건으로 사용할 것이므로

WHERE절이 아닌 HAVING절에 쓴다.

HAVING절은 GROUP BY와 ORDER BY 사이에 위치한다.

 

해커랭크 Top Competitors SQL

'SQL > 해커랭크' 카테고리의 다른 글

[SQL] 해커랭크 15 Days of Learning SQL  (0) 2022.09.09
[SQL] 해커랭크 SQL Project Planning  (0) 2022.09.07
[SQL] 해커랭크 The Report  (0) 2022.09.04
[SQL] 해커랭크 Occupations  (0) 2022.09.01
[SQL] 해커랭크 The PADS  (0) 2022.09.01
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 소스 코드

+ Recent posts