문제분석
문제설명이 상당히 긴 문제
근데 비교적 간단하다.
요점은, 스킬들이 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/
매우 설명이 잘되어있다.
요점은 누적합이라는 테크닉?, 알고리즘을 사용하는것이다.
첫번째 트라이와 효율성이 차이가나는점은 바로 범위만큼 강도를 더하고 빼는행위에서 차이가난다.
첫번째 방식에서 범위만큼 적용을 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 |
'알고리즘 > 프로그래머스 Level3' 카테고리의 다른 글
[프로그래머스 ,Java] Level3: 스티커 모으기 (0) | 2023.02.26 |
---|---|
[프로그래머스 ,Java] Level3: 셔틀버스 (0) | 2023.02.19 |
[프로그래머스,Java] Level3: 표현 가능한 이진트리 (1) | 2023.01.24 |
[프로그래머스,Java] Level3: 인사고과 (0) | 2023.01.24 |
[프로그래머스,Java] Level3: 억억단을 외우자 (0) | 2022.12.26 |