/** * https://leetcode.cn/problems/game-of-life/?envType=study-plan-v2&envId=top-interview-150 * @param {number[][]} board * @return {void} Do not return anything, modify board in-place instead. */ const gameOfLife = function (board) { }; /* 模拟:按照题目要求模拟,遍历所有的细胞,通过细胞周围的8个细胞来判断它下一次更新的状态,细胞的状态由下面的条件决定 1.细胞是活的,会有三种情况,如果周围活细胞数量小于2,那么这个细胞死亡,如果周围活细胞数量为2个或3个,那么这个细胞维持 存活状态,如果这个细胞周围的活细胞超过了三个,那么这个细胞死亡. 2.细胞是死的,如果周围正好有三个活细胞那么就复活这个细胞。 按照上面的要求我们可以把问题拆分为这样,如果这个细胞是活的 并且周围的活细胞少于两个,或者周围的活细胞大于三个,那么这个细胞死亡; 如果这个细胞是死的,周围正好有三个活细胞,那么就复活这个细胞 */ function f1(board) { const m = board.length - 1; const n = board[0].length - 1; let lives = 0; // 表示当前细胞周围的活细胞数量 const updates = []; // 细胞下一次要更新的状态 for (let i = 0; i <= m; i++) { for (let j = 0; j <= n; j++) { // 查看左上角的细胞是否存活 if (i > 0 && j > 0 && board[i - 1][j - 1] === 1) lives++; // 查看上面的细胞是否存活 if (i > 0 && board[i - 1][j] === 1) lives++; // 查看右上角的细胞是否存活 if (i > 0 && j < n && board[i - 1][j + 1] === 1) lives++; // 查看右边的细胞是否存活 if (j < n && board[i][j + 1] === 1) lives++; // 查看右下角的细胞是否存活 if (i < m && j < n && board[i + 1][j + 1] === 1) lives++; // 查看下面的细胞是否存活 if (i < m && board[i + 1][j] === 1) lives++; // 查看左下角的细胞是否存活 if (i < m && j > 0 && board[i + 1][j - 1] === lives) lives++; // 查看左边的细胞是否存活 if (j > 0 && board[i][j - 1] === 1) lives++; // 如果当前细胞是活的,只要它周围存活的细胞小于二,或者大于三,那么下一次更新的状态是死亡,把更新状态存入更新数组 if (board[i][j] === 1 && (lives < 2 || lives > 3)) { updates.push(0); continue; } // 如果当前细胞是死的, 只要周围存活的细胞恰好等于3,那么下次更新的状态就是复活,把更新状态存入更新数组 if (board[i][j] === 0 && lives === 3) { updates.push(1); continue; } // 如果细胞状态无需变化往更新数组插入数据-1,表示无需更新 updates.push(-1); } } // 通过updates更新数组来更新整个board let k = 0; for (let i = 0; i <= m; i++) { for (let j = 0; j <= n; j++) { if (updates[k] >= 0) board[i][j] = updates[k]; k++; } } } /* 利用次低位来保存下一次更新的状态,省去了updates更新数组的空间 */ function f2(board) { const dx = [-1, 0, 1, -1, 1, -1, 0, 1]; const dy = [-1, -1, -1, 0, 0, 1, 1, 1]; for (let i = 0; i < board.length; i++) { for (let j = 0; j < board[0].length; j++) { let sum = 0; // 计算周围8个邻居的活细胞数 for (let k = 0; k < 8; k++) { const nx = i + dx[k]; const ny = j + dy[k]; if (nx >= 0 && nx < board.length && ny >= 0 && ny < board[0].length) { sum += (board[nx][ny] & 1); // 累加邻居细胞的最低位(表示当前活或死) } } // // 根据规则设置细胞的未来状态 // if (board[i][j] === 1) { // // 如果当前细胞是活的 // if (sum === 2 || sum === 3) { // board[i][j] |= 2; // 设次低位为1,表示细胞将在下一轮继续存活 // } // } else { // // 如果当前细胞是死的 // if (sum === 3) { // board[i][j] |= 2; // 设次低位为1,表示细胞将在下一轮复活 // } // } // 根据规则设置细胞的未来状态 if (sum === 3 || (board[i][j] === 1 && (sum === 2 || sum === 3))) { board[i][j] |= 2; // 设次低位为1,表示细胞将在下一轮存活或复活 } } } // 第二次遍历,更新细胞的状态 for (let i = 0; i < board.length; i++) { for (let j = 0; j < board[i].length; j++) { board[i][j] >>= 1; // 右移1位,更新状态为新的细胞状态 } } }