这一题如果不是in place的话难度连easy都没有。就是列举几种不同的周边格子的状态然后判断当前格子的状态。具体状态看题意就知道了。要做in place的话也不难。因为原来的状态只有1和0两种,所以其实作为一个int你还有很多的空间可以发挥。譬如我们做状态判断的时候,我们取整型数的第二位去储存接下来即将变成的状态,然后依旧用第一位去做状态更迭的判断,这样就避免了Follow up 1中提到的问题。根据上述描述,可以得到代码如下:
private void _setNextByNeighbor(int[][] board, int x, int y) {
int livesCnt = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue;
if ((x + i < 0) || (x + i >= board.length)) continue;
if ((y + j < 0) || (y + j >= board[0].length)) continue;
if (board[x + i][y + j] % 2 == 1) livesCnt++;
}
}
if ((board[x][y] == 1 && (livesCnt == 3 || livesCnt == 2))
|| (board[x][y] == 0 && livesCnt == 3)) {
board[x][y] += 2;
}
}
public void gameOfLife(int[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
this._setNextByNeighbor(board, i, j);
}
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
board[i][j] >>= 1;
}
}
}
关于follow up 2,其实就是说如果棋盘无比巨大,内存一次过放不下怎么办?那就写进文件里一行行的读再分析呗。这一题要求内存最少能够读取三行的内容,这样你就可以先读三行,然后放进最上面的一行,然后读下一行继续。譬如先读1,2,3行,然后处理过之后放回第一行,读第四行,然后再放第二行,读第五行.....恰好,我还写过对应的代码,原因不详
public void calculateThreeLines(int[][] board) {
for (int i = 0; i < board[1].length; i++) {
int liveCnt = 0;
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
if (j == 0 && k == 0) continue;
if (board[1 + j] == null) continue;
if (k + i < 0 || k + i >= board[1].length) continue;
if (board[1 + j][k + i] % 2== 1) liveCnt++;
}
}
if (liveCnt >= 2 && liveCnt <= 3 && board[1][i] == 1) board[1][i] += 2;
else if (board[1][i] == 0 && liveCnt == 3) board[1][i] += 2;
}
}
public void convertOneLine(int[] outputLine) {
for (int i = 0; i < outputLine.length; i++) outputLine[i] /= 2;
}
public void gameOfLife() {
int[][] board = new int[3][];
board[1] = readLine();
while (board[1] != null) {
board[2] = readLine();
calculateThreeLines(board);
if (board[0] != null) {
convertOneLine(board[0]);
writeLine(board[0]);
}
board[0] = board[1];
board[1] = board[2];
}
if (board[0] != null) {
convertOneLine(board[0]);
writeLine(board[0]);
}
}