[JAVA] Lv2. 프렌즈4블록

김상윤·2022년 11월 22일
0
post-thumbnail
post-custom-banner

프렌즈4블록


[문제설명]

문제가 너무 길어서 생략하겠습니다..😇

[제한 조건]

마찬가지로 너무 길어서 생략..😇

위에 제시된 링크를 참조해주세요!


[나의 풀이]

import java.util.*;
class Solution {
    public static String[][] map;
    public static int answer;
    public int solution(int m, int n, String[] board) {
        answer = 0;
        
        map = new String[m][n];
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                map[i][j] = board[i].substring(j, j+1);
            }
        }
        
        // 지워질 블록이 있을때 까지 반복
        while(downBlocks(m, n));
        return answer;
    }
    
    // 지워질 블록이 있는가 체크, 있다면 내림
    public static boolean downBlocks(int m , int n) {
        boolean[][] chk = new boolean[m][n];
        for (int i = 0; i < m - 1; i++) {
            for (int j =0; j < n - 1; j++) {
                if (map[i][j].equals("0")) continue;
                if (check(i, j) == true) {
                    chk[i][j] = true;
                    chk[i+1][j] = true;
                    chk[i][j+1] = true;
                    chk[i+1][j+1] = true;
                }
            }
        }
        
        int cnt = 0;
        // chk가 true라면, 블록이 깨진것 따라서, 위의 블록이 있다면 아래로 내려야한다.
        for (int j = 0; j < n; j++) {
            List<String> list = new ArrayList<>();
            for (int i = m-1; i >= 0; i--) {
                if (chk[i][j] == true) {
                    cnt++;
                    continue;
                }
                list.add(map[i][j]);
            }
            
            for (int i = m-1, k = 0; i >= 0; i--, k++) {
                if (k < list.size()) map[i][j] = list.get(k);
                else map[i][j] = "0";
            }
        }
        answer += cnt;
        if (cnt == 0) return false;
        else return true;
    }
    
    // 4방향 체크
    public static boolean check(int r, int c) {
        String s = map[r][c];
        
        if (map[r+1][c].equals(s) && map[r][c+1].equals(s) && map[r+1][c+1].equals(s))
            return true;
        else return false;
    }
}

위 코드와 같이 작성해보았다.

두개의 함수로 나누어서 풀이해보았다. 각각의 함수는 아래와 같이 동작을 한다.

  • downBlocks : 2x2 블록 모든 것을 찾고 이것을 파괴시킨뒤 아래로 내리는 함수
  • check : 특정 좌표의 오른쪽, 하단, 대각선 오른쪽 아래를 체크하여 같은지를 확인하는 함수

😍 main

  • 주어진 board배열의 String을 2차원 String배열에 각 문자 하나하나를 쪼개어서 저장한뒤, while문을 통해 더 이상 지워지는 2x2 블록이 존재하지 않을 때까지 downBlocks를 시켜주어 문제를 해결하였다.

😇 downBlocks

  • 먼저 chk라는 boolean 이차원 배열을 만들었다. 해당 배열은 2x2 블록이 존재하는지를 체크하기 위한 용도이다. 그 다음 map의 각 원소를 돌면서, check 함수를 실행하여, 2x2 블록를 확인한뒤, 만약 박스가 형성되어 있다면, chk배열의 값을 true로 바꿔주었다. 이때, map에서 파괴된 블록들을 0으로 표현할 것이기 때문에, map에서 0으로 표현되어 있다면, 파괴된 부분이기 때문에 continue를 해준다.

  • 그 후, chk배열을 기준으로 chk가 true라면, 블록이 깨진것 따라서, 위의 블록이 있다면 아래로 내려야하기 때문에 ArrayList를 선언해준뒤, chk가 true가 아닌 원소들만 담아주었다. 이때, chk가 true라면 파괴된 블록이기 때문에 cnt값을 증가시켜주었다. 주의할 점은 아래로 내려야 하기 때문에 열 우선 탐색을 진행하여야 한다. (해당 부분은 직접 debug해보면 딱 알아차릴 수 있을것이다..!)

  • 최종적으로 ArrayList에 담긴 값으로 map을 update시켜준다. 이때, 길이가 맞지 않은 부분은 파괴되어 밑으로 내려간 부분이므로, "0"값으로 대체해준다.

  • cnt가 0이라면 파괴된 블록이 없다는 것을 의미하므로 false를 리턴한다. 그 반대는 true리턴

🤪 check

  • 특정원소를 인자로 받으면 해당 원소를 기준으로 오른쪽, 하단, 대각선 오른쪽 아래를 체크하여 같은지를 확인한다.

  • 만약 다 같으면 true, 하나라도 다를시 false를 리턴한다.

아래는 채점결과이다.

profile
알고리즘을 아직도 모르겠다
post-custom-banner

0개의 댓글