题目
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,
其中细胞的出生和死亡是同时发生的。
示例:
输入:
[
? [0,1,0],
? [0,0,1],
? [1,1,1],
? [0,0,0]
]
输出:
[
? [0,0,0],
? [1,0,1],
? [0,1,1],
? [0,1,0]
]
你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,
然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。
分析
1.首先还是观察题目,其实题目本身包含很多线索,比如该题其实主要就是活细胞与死细胞。
2.判断活细胞维持条件以及活->死,死->活的条件
3.根据条件可以判断我们需要建立一个功能函数,来判断某点周围八个方向的活细胞个数。根据返回的活细胞
个数来判断当前细胞状态。
4.但是不能直接修改题目所给的矩阵,因为会影响后面结果。所以我们可以做一个标记,比如活->死就是
由1变为-1,死->活就是0变2.
5.然后最后再遍历所给矩阵,然后将约定好的-1变为0,2变为1,此时就完成游戏,返回结果
附注:
1.对于八个方向,全部遍历,可以采用全部随机遍历,把所有方向的坐标变换的方式全部罗列出来,就是
代码中的dx[],dy[]。然后遍历进行组合,然后将所获取的坐标取出来,看矩阵中的值,然后记录,遍历
完成返回结果。即活细胞的计数(需要注意不要漏掉原先是活细胞但是按照约定更改值后的点)
2.对于更改题目中原始矩阵导致影响后续判断的情况:
(1)复制一个矩阵负责取数据计算,然后原始矩阵就可以修改
(2)设计一个简单的算法约定,然后按照约定修改原始值,最后需要修改回题目要求的结果。同时,
计算时也要考虑算法约定的情况,否则会漏掉。
#include<vector>
using namespace std;
class MyClass
{
public:
void gameOfLife(vector<vector<int>>& board) {
if (board.empty())
{
return;
}
int row = board.size();
int col = board[0].size();
for (int i = 0; i < row; ++i){
for (int j = 0; j < col; ++j){
if (board[i][j] == 1){
int lifeCnt = getLifeCount(board, i, j);
if (lifeCnt < 2 || lifeCnt>3){
board[i][j] = -1;
}
else
{
continue;
}
}
if (board[i][j] == 0){
int lifeCnt = getLifeCount(board, i, j);
if (lifeCnt == 3){
board[i][j] = 2;
}
}
}
}
for (int i = 0; i < row; ++i){
for (int j = 0; j < col; ++j){
if (board[i][j] == 2){
board[i][j] = 1;
}
if (board[i][j] == -1){
board[i][j] = 0;
}
}
}
return;
}
int getLifeCount(const vector<vector<int>>& board,int x,int y){
int dx[] = { 0, -1, 1, -1, 1, 0, -1, 1 };
int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int row = board.size();
int col = board[0].size();
int lifeCnt = 0;
for (int i = 0; i < 8; ++i){
if (x + dx[i] >= 0 && x + dx[i] < row&&y + dy[i] >= 0 && y + dy[i] < col){
if (board[x + dx[i]][y + dy[i]] == 1 || board[x+dx[i]][y+dy[i]] == -1){
++lifeCnt;
}
}
}
return lifeCnt;
}
};