题目来源
题目描述
题意分析
本题的两个关键点
(1)其生存规律总结如下
(2)前一秒变过的细胞状态不会影响下一个细胞状态。问题是新的状态是基于初始状态来变化的,但是如果修改了原数组,会影响后继状态的判断。怎么办呢?
- 复制一个初始状态,然后修改board
- 使用位运算
使用位运算
一个 int 有 32 bit,输入数据只用了一个 bit,所以我们可以利用其他空闲的bit位进行“原地修改”。
- 1代表细胞活的, 0 代表细胞死的,那么这个位置就四种状态,用【下一个状态,当前状态】表示,最后需要用右移操作更新结果
- 状态 0: 00 ,死的,下一轮还是死的
- 状态 1: 01,活的,下一轮死了
- 状态 2: 10,死的,下一轮活了
- 状态 3: 11,活的,下一轮继续活着
- 进一步:下一轮活的可能有两种,也就是要把单元格变为1
- 这个活细胞周围八个位置有两个或三个活细胞,下一轮继续活,属于11
- 这个细胞本来死的,周围有三个活着的,下一轮复活了,属于 10
那遍历下每个格子看他周围细胞有多少个活细胞就行了,然后更改为状态,那么对于第一种可能,把 board[i][j]设置为 33,对于第二种可能状态设置为 2,设置个高位flag,遍历后面的格子,拿到与他相邻的格子中有多少个 alive 的,和 1与一下即可,最后我们把 board[i][j]右移 1位,更新结果
class Solution {
std::vector<std::vector<int>> dirs {
{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
{0, 1}, {1, -1}, {1, 0}, {1, 1}
};
// 当前位置范围内有多少活细胞
int liveCount( vector<vector<int>> &board, int i, int j){
int N = board.size(), M = board[0].size();
int ans = 0;
for(auto d : dirs){
int pi = i + d[0], pj = j + d[1];
if(pi < 0 || pj < 0 || pi == N || pj == M){
continue;
}
// 如果这个位置为 0,代表当前轮是死的,不需要算进去
// 如果这个位置为 1,代表当前轮是活得,需要算进去
// 如果这个位置为 2,代表当前轮是死的(状态10,下一轮是活的),不需要算进去
// 如果这个位置为 3,代表是当前轮是活的(状态11,下一轮也是活的),需要算进去
ans += (board[pi][pj] & 1);
}
return ans;
}
public:
void gameOfLife(vector<vector<int>>& board) {
if(board.empty() || board[0].empty()){
return;
}
int N = board.size(), M = board[0].size();
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
// 拿到当前位置周围活细胞数量
int cnt = liveCount(board, i, j);
// 1. 活细胞周围八个位置有两个或三个活细胞,下一轮继续活
if (board[i][j] == 1 && (cnt == 2 || cnt == 3)) board[i][j] = 3;
// 2. 死细胞周围有三个活细胞,下一轮复活了
if (board[i][j] == 0 && cnt == 3) board[i][j] = 2;
}
}
// 更新结果
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
board[i][j] >>= 1;
}
}
}
};
使用辅助数组
class Solution {
std::vector<std::vector<int>> dirs {
{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
{0, 1}, {1, -1}, {1, 0}, {1, 1}
};
// 当前位置范围内有多少活细胞
int liveCount( vector<vector<int>> &original, int i, int j){
int N = original.size(), M = original[0].size();
int ans = 0;
for(auto d : dirs){
int pi = i + d[0], pj = j + d[1];
if(pi < 0 || pj < 0 || pi == N || pj == M){
continue;
}
ans += original[pi][pj];
}
return ans;
}
public:
void gameOfLife(vector<vector<int>>& board) {
if(board.empty() || board[0].empty()){
return;
}
vector<vector<int>> original = board;
int N = original.size(), M = original[0].size();
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
int cnt = liveCount(original, i, j);
if((original[i][j] == 0 && cnt == 3)
|| (original[i][j] == 1 && (cnt == 2 || cnt == 3))){
board[i][j] = 1;
}else{
board[i][j] = 0;
}
}
}
}
};