因为要求in-place,所以要用状态机状态转换的方法:
状态0: 死细胞转为死细胞
状态1: 活细胞转为活细胞
状态2: 活细胞转为死细胞
状态3: 死细胞转为活细胞
最后我们对所有状态对2取余,那么状态0和2就变成死细胞,状态1和3就是活细胞,达成目的。我们先对原数组进行逐个扫描,对于每一个位置,扫描其周围八个位置,如果遇到状态1或2,就计数器累加1,扫完8个邻居,如果少于两个活细胞或者大于三个活细胞,而且当前位置是活细胞的话,标记状态2,如果正好有三个活细胞且当前是死细胞的话,标记状态3。完成一遍扫描后再对数据扫描一遍,对2取余变成我们想要的结果。
class Solution {
public:
void gameOfLife(vector<vector<int> >& board) {
int m = board.size(), n = m ? board[0].size() : 0;
int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int cnt = 0;
for (int k = 0; k < 8; ++k) {
int x = i + dx[k], y = j + dy[k];
if (x >= 0 && x < m && y >= 0 && y < n && (board[x][y] == 1 || board[x][y] == 2)) {
++cnt;
}
}
if (board[i][j] && (cnt < 2 || cnt > 3)) board[i][j] = 2;
else if (!board[i][j] && cnt == 3) board[i][j] = 3;
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
board[i][j] %= 2;
}
}
}
};
上面的代码是网上找到的,我自己照着这个思路写了一份,用了8个if来判断,不仅非常麻烦,而且容易出错,不如直接用数组dx,只需要限制经过计算的x,y的范围就好了(x >= 0 && x < m && y >= 0 && y < n )。还有一个需要注意的地方,x是列,y是行。