정확성100, 효율성 0 코드
class Solution {
public int solution(int[][] board, int[][] skill) {
int answer = 0;
answer=board.length*board[0].length;
for (int[] nowSkill : skill) {
int type=nowSkill[0];
int modi;
if(type==1)
modi=-1;
else modi=1;
int startX=nowSkill[1];
int startY=nowSkill[2];
int endX=nowSkill[3];
int endY=nowSkill[4];
int degree=nowSkill[5];
for (int i = startX; i <=endX ; i++) {
for (int j = startY; j <=endY ; j++) {
boolean flag=false;
if(board[i][j]>0)
flag=true;
board[i][j]+=degree*modi;
if(board[i][j]>0){
//해당 스킬 시행 후 벽이 존재하는 경우, 기존에 있던 벽이라면 벽 개수 변화X / 기존에 벽이 없었다면 벽 갯수 ++
if(!flag)
answer++;
}else{
//스킬 시행 후 벽 소멸, 기존의 벽 있었으면 벽 갯수 -- / 원래 없었으면 변화 X
if(flag)
answer--;
}
}
}
}
return answer;
}
}
통과 코드(정확성 100, 효율성 100)
class Solution {
public int solution(int[][] board, int[][] skill) {
int answer = 0;
int[][] skillBoard=new int[board.length+1][board[0].length+1];
for (int[] nowSkill : skill) {
int type=nowSkill[0];
int modi;
if(type==1)
modi=-1;
else modi=1;
int startX=nowSkill[1];
int startY=nowSkill[2];
int endX=nowSkill[3];
int endY=nowSkill[4];
int degree=nowSkill[5];
skillBoard[startX][startY]+=degree*modi;
skillBoard[endX+1][startY]-=degree*modi;
skillBoard[startX][endY+1]-=degree*modi;
skillBoard[endX+1][endY+1]+=degree*modi;
}
for (int i = 1; i < board[0].length; i++) {
for (int j = 0; j <board.length; j++) {
skillBoard[j][i]+=skillBoard[j][i-1];
}
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j <board[0].length; j++) {
if(i==0){
if(skillBoard[i][j]+board[i][j]>0)
answer++;
}else{
skillBoard[i][j]+=skillBoard[i-1][j];
if(skillBoard[i][j]+board[i][j]>0)
answer++;
}
}
}
return answer;
}
}
처음엔 왜이렇게 쉬운 문제가 나왔지? 싶었는데, 역시 쉬운 문제가 아니였다..
단순히 정답을 산출하는 건 쉬운 문제지만, 이 문제를 효율적으로 풀기 위해선 2차원 누적합을 사용해야 한다.
누적합이란 Si=Si-1+Ai를 이용해서 푸는 방식인데
내가 0번 인덱스부터 2번 인덱스까지 2를 추가하고 싶다면 loop를 돌면서 각 값에 +2를 해주는 것이 아니라,
누적합 배열을 만들어 0번 인덱스에 2 3번인덱스에 -2를 더해준다.
그렇게 되면 누적합 개념을 사용해서 나중에 필요한 상황에서, 결과값[1] = 누적합[0]+배열[1] 이런식으로 간편하게 사용할 수 있게 되는 것이다.
이는, 2차원으로 확장해도 같은데 1,1 부터 2,2까지 2를 더하고 싶다면 누적합[1,1]에 2를 더하고 누적합[2+1,1], [1,2+1]에 2를 빼고 누적합[2+1,2+1]엔 2를 다시 더해주고 오른쪽으로 누적합을 한번 쭉 돌리고 (모든 행) , 아래로 누적합을 쭉 돌리면 (모든 열) 결과배열을 구할 수 있게 된다.
주의할 점은, 여기선 스킬이 최대25만개이기에 각 스킬이 적용되는 직사각형의 넓이를 N이라 했을 떄 스킬 배열의 크기*N번의 반복이 발생하게 된다. 이 값과 배열을 선회하는 비용을 비교했을 때 스킬이 충분히 이득이 된다고 판단되면 누적합을 적용해야 한다.
여기선 배열의 최대 크기는 100만이고 스킬이 25만개*N인데, 여기서 N은 충분히 클 수 있기 때문에 배열을 선회하는 비용보다 스킬마다 반복을 하는 행위가 훨씬 큰 부담이 되기에 누적합을 사용해야 한다.
'Algorithm > Programmers' 카테고리의 다른 글
[Lv.3] 광고 삽입 (0) | 2023.04.14 |
---|---|
[Lv.3] 양과 늑대 (0) | 2023.04.13 |
[Lv.3] 다단계 칫솔 판매 (0) | 2023.04.13 |
[Lv.3] 자물쇠와 열쇠 (0) | 2023.04.13 |
[Lv.3] 경주로 건설 (0) | 2023.04.12 |