알고리즘/프로그래머스 Level3

[프로그래머스, Java] Level3 : 파괴되지않는 건물

류창 2023. 1. 30. 15:25
반응형

 

 

문제분석

문제설명이 상당히 긴 문제

 

근데 비교적 간단하다.

 

요점은,  스킬들이 Type으로 공격과 치유를 구분하고,  범위와 강도가 주어진다.

공격과 치유를 적용한뒤, 파괴되지않는 건물을 리턴하면된다.

 

 

이게끝? 맞다 이게끝이다. 

 

 

First Try: 2차반복문 사용

 

누구나 생각할 풀이방법이다.   스킬을 순회하며, 각 스킬마다 적용되는 범위에다 강도를 빼주거나 더한다.

 

그후, 마지막에 파괴된건물이 있는지 한번확인한다.

이렇게 하면 정확성은 100%다.

 

실제 카카오 테스트때도 50%응시자가 이와같은 코드를 짯다.

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
class Solution {
    public int solution(int[][] board, int[][] skill) {
        int answer = board.length*board[0].length;     
        
        for(int[] sk:skill){
            int type = sk[0];
            int y1 = sk[1];
            int x1 = sk[2];
            int y2 = sk[3];
            int x2 = sk[4];
            int degree = sk[5];
            if(type==1){
                for(int i=y1;i<=y2;i++){
                    for(int j=x1;j<=x2;j++){
                        board[i][j]-=degree;
                    }
                }
            }
            else{
                for(int i=y1;i<=y2;i++){
                    for(int j=x1;j<=x2;j++){
                        board[i][j]+=degree;
                    }
                }
            }
        }
        
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(board[i][j]<=0){
                    answer--;
                }
            }
        }
        
        return answer;
    }
}
cs

 

하지만 당연하게도, 효율성 에러가 떳다.

 

 

Second Try: 효율성에 고찰

아무리 생각해봐도 이거보다 더 효율성을 줄일 방법이 생각나지않았다.

 

스킬의 목록을 탐색하는것은 필수고,  스킬의 범위만큼 강도만큼 더하고 빼는행위도 필수적이기때문이다.

 

결국.. 카카오 해설을 참고하게되었다.

 

https://tech.kakao.com/2022/01/14/2022-kakao-recruitment-round-1/

 

2022 카카오 신입 공채 1차 온라인 코딩테스트 for Tech developers 문제해설

지난 2021년 9월 11일 토요일 오후 2시부터 7시까지 5시간 동안 2022 KAKAO BLIND RECRUITMENT 1차 코딩 테스트가 진행되었습니다. 테스트에는 총 7개의 문제가 출제되었으며, 개발 언어는 C++, Java, JavaScript, K

tech.kakao.com

 

매우 설명이 잘되어있다.

 

요점은 누적합이라는 테크닉?, 알고리즘을 사용하는것이다. 

 

첫번째 트라이와 효율성이 차이가나는점은 바로 범위만큼 강도를 더하고 빼는행위에서 차이가난다.

 

첫번째 방식에서 범위만큼 적용을 y2-y1 *  x2-x1 만큼 연산을 무조건했다면,

누적합을 사용하면 꼭짓점만 미리 표시를 찍어두는걸로 겨우 4만큼의 연산만하면 마지막에 처리가 가능하다.

 

즉 ,(y2-y1 *  x2-x1)*N  vs  4*N+N 같은 느낌이다. 후자가 당연히 빠를수밖에없다.

 

이런 기발한 생각을 어떻게하는지 놀라울따름이다 .

 

 

나중에 누적합을 한번에 하기위해 밑작업? 좌표를 셋팅한다.

각 꼭짓점 4좌표에다가 박아둔다.

 

 

x좌표 (좌에서 우), y좌표(위에서 아래)를 누적합을 진행한다.

 

누적합을 진행한 결과와 기존 내구도를 더해서, 파괴된건물은 빼준다.

  

전체풀이

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
46
47
48
49
50
51
52
53
54
import java.util.*;
class Solution {
    public int solution(int[][] board, int[][] skill) {
        int answer = board.length*board[0].length;     
        
        int[][] sboard = new int[board.length+1][board[0].length+1];
        
        //누적합 할 좌표 셋팅
        for(int[] sk:skill){
            int type = sk[0];
            int y1 = sk[1];
            int x1 = sk[2];
            int y2 = sk[3];
            int x2 = sk[4];
            int degree = sk[5];
            
            if(type==1){
                sboard[y1][x1]-=degree;
                sboard[y1][x2+1]+=degree;
                sboard[y2+1][x1]+=degree;
                sboard[y2+1][x2+1]-=degree;
            }else{
                sboard[y1][x1]+=degree;
                sboard[y1][x2+1]-=degree;
                sboard[y2+1][x1]-=degree;
                sboard[y2+1][x2+1]+=degree;
            }
        }
        
        //X좌표 누적합
         for(int i=0;i<sboard.length;i++){
            for(int j=1;j<sboard[0].length;j++){
                sboard[i][j]+=sboard[i][j-1];
            }
         }
        //Y좌표 누적합
        for(int i=1;i<sboard.length;i++){
            for(int j=0;j<sboard[0].length;j++){
                sboard[i][j]+=sboard[i-1][j];
            }
         }
        
        //기존 보드 + 누적합결과
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(board[i][j]+sboard[i][j]<=0){
                    answer--;
                }
            }
        }
        
        return answer;
    }
}
cs
반응형