# 289. Game of Life
### Idea
題目要求將生存遊戲 boards 的格點置換為**下一個狀態**<br/>
先不考慮空間複雜度<br/>
最直覺的解法是
1. 創建一個儲存下一個狀態的二維陣列 results
2. 遍歷每個格點把下一個狀態存取到 results (**要小心處理訪問陣列的上下界**)
3. 再遍歷一次將 boards 的格點取代為 results 的格點
時間複雜度為 O( m _ n )<br/>
空間複雜度為 O( m _ n )
```javascript
function gameOfLife(board) {
const m = board.length,
n = board[0].length,
results = Array.from(Array(m), (_) => Array(n))
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
results[i][j] = setStatus(board, i, j, m, n)
}
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
board[i][j] = results[i][j]
}
}
}
function setStatus(board, x, y, m, n) {
let liveCount = 0
for (let i = Math.max(0, x - 1); i <= Math.min(m - 1, x + 1); i++) {
for (let j = Math.max(0, y - 1); j <= Math.min(n - 1, y + 1); j++) {
if (i !== x || j !== y) liveCount += board[i][j] === 1
}
}
return Number(
board[x][y] === 1 ? liveCount >= 2 && liveCount <= 3 : liveCount === 3
)
}
```
### Refactor
因為實際狀態本身很單純只有生存或死亡<br/>
可以透過**自定義拓展狀態**來最佳化空間的利用<br/>
我們定義每個格點的假想狀態含有**時間變化的意義**(**變化前 → 變化後**)
- status = 1, 生存 → 生存
- status = 2, 死亡 → 生存
- status = 3, 生存 → 死亡
- status = 4, 死亡 → 死亡
有了定義的認知後
想法跟前面的思路大體一致
只需要留意以下兩點
1. 在計算各點的假想狀態時將假想狀態的變化前實際狀態考慮進去
2. 遍歷將全部假想狀態正確轉換回實際狀態
時間複雜度為 O( m \* n )<br/>
空間複雜度為 O( 1 )
```javascript
function gameOfLife(board) {
/*
status of board definition:
0 = dead before, dead after.
1 = alive before, alive after.
2 = alive before, dead after.
3 = dead before, alive after.
*/
const m = board.length,
n = board[0].length
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
board[i][j] = setStatus(board, i, j, m, n)
}
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
board[i][j] %= 2
}
}
}
function setStatus(board, x, y, m, n) {
let liveCount = 0
for (let i = Math.max(0, x - 1); i <= Math.min(m - 1, x + 1); i++) {
for (let j = Math.max(0, y - 1); j <= Math.min(n - 1, y + 1); j++) {
if (i !== x || j !== y) {
if (board[i][j] === 2) liveCount += 1
else if (board[i][j] === 3) liveCount += 0
else liveCount += board[i][j]
}
}
}
if (board[x][y] === 1 && (liveCount < 2 || liveCount > 3)) return 2
else if (board[x][y] === 0 && liveCount === 3) return 3
else return board[x][y]
}
```
###### tags: `Leetcode` `JavaScript`