프로그래머스 LEVEL 3(파괴되지 않은 건물)

-
사용 언어 : javascript
-
해결 날짜 : 2023-05-05
-
해결 방법 :
- 누적합을 통해 문제 해결
- skill을 돌며 공격, 회복에 대한 누적합 저장
- 우측으로 누적합, 아래측으로 누적합 계산
- board와 누적합 계산
- 누적합을 통해 문제 해결
-
회고 :
-
처음 작성한 코드
function solution(board, skill) { skill.forEach(([type, r1, c1, r2, c2, degree]) => { const sign = type === 1 ? -1 : 1; for (let x = c1; x <= c2; x++) { for (let y = r1; y <= r2; y++) { board[y][x] += sign * degree; } } }); return board.flat().filter((v) => v >= 1).length; } -
당연하게도 효율성 테스트에서 전부 시간 초과가 발생했다..

-
곰곰이 생각한 결과 누적합을 통해 문제를 해결할 수 있다 생각하여 아래와 같이 작성하였다.
function solution(board, skill) { const maxX = board[0].length, maxY = board.length; const prefixSum = Array.from({ length: maxY + 1 }, () => Array.from({ length: maxX + 1 }, () => 0), ); skill.forEach(([type, r1, c1, r2, c2, degree]) => { const d = type === 1 ? -1 * degree : degree; prefixSum[r1][c1] += d; prefixSum[r2 + 1][c2 + 1] += d; prefixSum[r1][c2 + 1] -= d; prefixSum[r2 + 1][c1] -= d; }); for (let y = 0; y <= maxY; y++) { for (let x = 1; x <= maxX; x++) { prefixSum[y][x] += prefixSum[y][x - 1]; } } for (let x = 0; x <= maxX; x++) { for (let y = 1; y <= maxY; y++) { prefixSum[y][x] += prefixSum[y - 1][x]; } } return board.map((rows, i) => rows.filter((v, j) => v + prefixSum[i][j] >= 1)).flat().length; }
- 그 결과 효율성 테스트에서 7개 중 하나를 통과하지 못했다.. 아마 마지막 테스트 케이스의 배열 크기가 너무 커서 생긴 문제라고 생각되었다.
- flat()에서 시간이 오래 소요된 것 같아서 공식 문서를 찾아보니 flat() 메소드도 어찌 됐든 모든 원소를 돌아야 하기 때문에 2차원 배열인 경우 O(N * M)의 시간 복잡도를 갖게 된다는 것을 알게 되었다.
-
따라서 flat() 메소드 대신 다른 방법을 사용했다.
return board.reduce( (acc, cur, i) => acc + cur.filter((v, j) => v + prefixSum[i][j] >= 1).length, 0, ); -
통과!!

- 평소에 2차원 배열을 1차원 배열로 변환할 때 flat() 메서드를 자주 사용했는데 위와 같이 작성하면 한번 더 배열을 도는 꼴이므로 잘 생각하고 사용해야 겠다고 느꼈다.
-
-
코드
function solution(board, skill) { const maxX = board[0].length, maxY = board.length; const prefixSum = Array.from({ length: maxY + 1 }, () => Array.from({ length: maxX + 1 }, () => 0), ); skill.forEach(([type, r1, c1, r2, c2, degree]) => { const d = type === 1 ? -1 * degree : degree; prefixSum[r1][c1] += d; prefixSum[r2 + 1][c2 + 1] += d; prefixSum[r1][c2 + 1] -= d; prefixSum[r2 + 1][c1] -= d; }); for (let y = 0; y <= maxY; y++) { for (let x = 1; x <= maxX; x++) { prefixSum[y][x] += prefixSum[y][x - 1]; } } for (let x = 0; x <= maxX; x++) { for (let y = 1; y <= maxY; y++) { prefixSum[y][x] += prefixSum[y - 1][x]; } } return board.reduce( (acc, cur, i) => acc + cur.filter((v, j) => v + prefixSum[i][j] >= 1).length, 0, ); } -
출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges