코딩테스트 연습 - 파괴되지 않은 건물 | 프로그래머스 스쿨
이 문제의 핵심은 시간복잡도를 줄임에 있다.
skill 이 발동될 때, 범위에 있는 건물 모두에 데미지를 주는 방법은 당연히 안된다.skill.length * H * W 가 되버린다.skill 이 발동될 때마다 간편하게 기록하고, 나중에 다시 이를 활용하는 방법이 있다.skill 이 발동될 때마다, 범위의 모든 행에다가 기록을 하게 되면 최대 skill.length * H 가 된다.누적합의 누적합으로 풀어야하는 문제인 것이다.O(skill.length + H * W);
class Solution {
public int H;
public int W;
public int[][] b;
public int[][] sum;
public void execute(int r1, int c1, int r2, int c2, int damage) {
sum[r1][c1] += damage;
sum[r2 + 1][c1] -= damage;
sum[r1][c2 + 1] -= damage;
sum[r2 + 1][c2 + 1] += damage;
}
public void print() {
for (int i = 0; i < H + 1; i++) {
for (int j = 0; j < W + 1; j++) {
System.out.print(sum[i][j] + " ");
}
System.out.println();
}
System.out.println("===========");
}
public int solution(int[][] board, int[][] skill) {
this.H = board.length;
this.W = board[0].length;
this.b = board;
this.sum = new int[H + 1][W + 1];
for (int i = 0; i < skill.length; i++) {
int type = skill[i][0] == 1 ? -1 : 1;
execute(skill[i][1], skill[i][2], skill[i][3], skill[i][4], type * skill[i][5]);
// print();
}
int add = 0;
for (int i = 0; i < W + 1; i++) {
int value = 0;
for (int j = 0; j < H + 1; j++) {
value += sum[j][i];
sum[j][i] = value;
}
}
for (int i = 0; i < H; i++) {
for (int j = 0; j < W + 1; j++) {
add += sum[i][j];
if (j != W) {
b[i][j] += add;
}
}
}
int answer = 0;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (0 < b[i][j]) {
answer++;
}
}
}
return answer;
}
}
멋진 풀이네요.