3 minute read



상세한 문제 내용은 여기에서 확인 바랍니다.

입출력 예시

Input
board = [[0,0,0,0,0],[0,0,1,0,3],[0,2,5,0,1],[4,2,4,4,2],[3,5,1,3,1]]
moves = [1,5,3,5,1,2,1,4]
Output
4


문제 풀이

문제 풀이를 위해 다음과 같은 아이디어를 도출하였다.

  • 주어진 크레인 2차원 배열을 그대로 쓰는 것보단 인형뽑기를 하기 쉽도록 2차원 배열을 회전하여 활용하자.
  • 인형뽑기하여 담는 바구니는 스택을 활용하여 구현하자.

2차원 배열 회전하기

먼저 주어진 board 2차원 배열을 크레인에서 뽑기 쉽게 회전해야 한다.
내가 생각한 회전 방법은 우측으로 90도를 회전하고 뒤집는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 주어진 board 2차원 배열
0 0 0 0 0 
0 0 1 0 3
0 2 5 0 1
4 2 4 4 2
3 5 1 3 1

// 우측으로 90도 회전 후
0 3 1 2 1
0 0 0 4 3
0 1 5 4 1
0 0 2 2 5
0 0 0 4 3

// 앞, 뒤 뒤집기
0 0 0 4 3
0 0 2 2 5
0 1 5 4 1
0 0 0 4 3
0 3 1 2 1

위 내용을 코드로 작성해보자.

1
2
3
4
5
6
for(int i=0; i<board.length; i++) {
    for(int j=0; j<board[i].length; j++) {
        new_board[i][j] = board[j][board.length-i-1]; // 우측으로 90도 회전
    }
}
Collections.reverse(Arrays.asList(new_board)); // 2차원 배열의 순서 뒤집기


작성하고 나서 생각해보니, 우측으로 90도 회전하고 뒤집지 않고 한번에 왼쪽으로 90도 회원하는 코드를 작성하고 싶어 다시 고쳤다.

1
2
3
4
5
for(int i=0; i<board.length; i++) {
    for(int j=0; j<board[i].length; j++) {
        new_board[board[i].length-i-1][j] = board[j][board.length-i-1]; // 우측으로 90도 회전
    }
} 

위 코드와 같이 우측으로 90도 뒤집은 상태에서 인덱스를 뒤집어서 집어넣을 수 있도록 하니, 깔끔하게 해결되었다.

1
2
3
4
5
6
7
8
9
10
11
12
0 0 0 0 0 
0 0 1 0 3
0 2 5 0 1
4 2 4 4 2
3 5 1 3 1

// 왼쪽으로 90도 회전
0 0 0 4 3
0 0 2 2 5
0 1 5 4 1
0 0 0 4 3
0 3 1 2 1


인형뽑기 게임 구현하기

이제 인형뽑기 할 수 있는 크레인 배열을 구했으니 실제로 인형뽑기하여 바구니에 쌓도록 해야하는데,
크레인 작동위치 배열 moves 만큼 반복하며 moves에 담긴 원소별로 크레인 위치마다 인형을 뽑아야 한다.

  1. 3중 반복문을 활용해 크레인 작동 위치(moves)별로 반복하며 크레인 배열(new_board)에서 0이 아닌 인형을 뽑는다.
  2. 뽑은 인형의 위치를 0으로 변경한다.
  3. 인형을 뽑아 바구니(스택)에 쌓는다.
  4. 뽑은 인형과 바구니에 맨 위 인형과 같다면 연속으로 인형을 뽑은 것이기에 터뜨린다.(스택에서 맨 위 인형 제거)

위 로직을 코드로 작성해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(int i=0; i<moves.length; i++) {
    for(int j=0; j<new_board.length; j++) {
        for(int k=0; k<new_board[j].length; k++) {
            if((moves[i]-1) == j && new_board[j][k] != 0) {
                if(!result.empty() && result.peek()==new_board[j][k]) {
                    result.pop();
                    answer += 2;
                }
                else result.push(new_board[j][k]);
                new_board[j][k] = 0;
                break;
            }
        }
    }
}

조금 복잡해보이지만 간단히 정리하자면,
두번째 인형을 뽑을 때부터 연속된 인형을 뽑았을 경우 스택에 쌓지 않고 제거하여 연속으로 뽑은 인형을 검증할 수 있다.


작성 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.*;

class Solution {
    public static void main(String[] args) {
        
        int[][] board = {{0,0,0,0,0},{0,0,1,0,3},{0,2,5,0,1},{4,2,4,4,2},{3,5,1,3,1}};
        int[] moves = {1,5,3,5,1,2,1,4};
        // int[][] board = {{0,0,0,0,0},{0,0,0,1,3},{3,1,5,4,2},{1,2,3,4,5},{3,2,1,4,5}};
        // int[] moves = {1,5,4,2,3};
        
        long start = System.currentTimeMillis();
        solution(board, moves);
        long end = System.currentTimeMillis();
        System.out.println("\n수행시간 = " + (end-start));
    }
    
    public static int solution(int[][] board, int[] moves) {
        int answer = 0;
        int[][] new_board = new int[board.length][board.length];
        Stack<Integer> result = new Stack<>();
        
        for(int i=0; i<board.length; i++) {
            for(int j=0; j<board[i].length; j++) {
                new_board[board[i].length-i-1][j] = board[j][board.length-i-1]; // 왼쪽으로 90도 회전 및 상,하 뒤집기
            }
        } 

        for(int i=0; i<moves.length; i++) {
            for(int j=0; j<new_board.length; j++) {
                for(int k=0; k<new_board[j].length; k++) {
                    if((moves[i]-1) == j && new_board[j][k] != 0) {
                        if(!result.empty() && result.peek()==new_board[j][k]) {
                            result.pop();
                            answer += 2;
                        }
                        else result.push(new_board[j][k]);
                        new_board[j][k] = 0;
                        break;
                    }
                }
            }
        }
        return answer;
    }
}

회고

  • 2차원 배열을 회전하는 과정에서 많이 헷갈리는 부분이 많았다. 배열 회전이나 뒤집기 활용도 꾸준히 복습해야 겠다.
  • 스택을 본격적으로 활용하며 특정 순서별로 제거해야 했지만, 짝 맞추는 것으로 헷갈려 인형을 터뜨리는 로직 구현에 오랜 시간이 걸렸다..ㅠ