問題:數組
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."this
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):編碼
Write a function to compute the next state (after one update) of the board given its current state.spa
Follow up: three
解決:遊戲
【題意】 ip
這道題是有名的康威生命遊戲, 這是一種細胞自動機,每個位置有兩種狀態,1爲活細胞,0爲死細胞,對於每一個位置都知足以下的條件:ci
1. 若是活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡;get
2. 若是活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;it
3. 若是活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡;
4. 若是死細胞周圍正好有三個活細胞,則該位置死細胞復活;
題目要求咱們用置換方法in-place來解題,因此咱們就不能新建一個相同大小的數組,那麼咱們只能更新原有數組,可是題目中要求全部的位置必須被同時更新,可是在循環程序中咱們仍是一個位置一個位置更新的,那麼當一個位置更新了,這個位置成爲其餘位置的neighbor時,咱們怎麼知道其未更新的狀態呢,咱們能夠使用狀態機轉換:
狀態0(00): 死細胞轉爲死細胞
狀態1(01): 活細胞轉爲活細胞
狀態2(10): 活細胞轉爲死細胞
狀態3(11): 死細胞轉爲活細胞
咱們將全部狀態對2取餘,那麼狀態0和2就變成死細胞,狀態1和3就是活細胞,達成目的。
① 直接實現上面的解法。
class Solution{ //0ms
public void gameOfLife(int[][] board){
int m = board.length;
int n = board[0].length;
for (int i = 0;i < m;i ++){
for (int j = 0;j < n;j ++){
int lives = 0;
if (i > 0){//判斷上邊
lives += board[i - 1][j] == 1 || board[i - 1][j] == 2 ? 1 : 0;//狀態1,2初始爲活細胞
}
if (j > 0){//判斷左邊
lives += board[i][j - 1] == 1 || board[i][j - 1] == 2 ? 1 : 0;
}
if (i < m - 1){//判斷下邊
lives += board[i + 1][j] == 1 || board[i + 1][j] == 2 ? 1 : 0;
}
if (j < n - 1){//判斷右邊
lives += board[i][j + 1] == 1 || board[i][j + 1] == 2 ? 1 : 0;
}
if (i > 0 && j > 0){//判斷左上角
lives += board[i - 1][j - 1] == 1 || board[i - 1][j - 1] == 2 ? 1 : 0;
}
if (i < m - 1 && j < n - 1){//判斷右下角
lives += board[i + 1][j + 1] == 1 || board[i + 1][j + 1] == 2 ? 1 : 0;
}
if (i > 0 && j < n - 1){//判斷右上角
lives += board[i - 1][j + 1] == 1 || board[i - 1][j + 1] == 2 ? 1 : 0;
}
if (i < m - 1 && j > 0){//判斷左下角
lives += board[i + 1][j - 1] == 1 || board[i + 1][j - 1] == 2 ? 1 : 0;
}
if (board[i][j] == 0 && lives == 3){//死細胞轉換爲活細胞
board[i][j] = 3;
}else if (board[i][j] == 1){//活細胞轉爲死細胞
if (lives < 2 || lives > 3) board[i][j] = 2;
}
}
}
//解碼
for (int i = 0;i < m;i ++){
for (int j = 0;j < n;j ++){
board[i][j] = board[i][j] % 2;
}
}
}
}
② 使用位操做進行編碼。
class Solution{ //1ms public void gameOfLife(int[][] board){ int m = board.length, n = board[0].length; for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ int lives = 0; // 累加上下左右及四個角還有自身的值 for(int y = Math.max(i - 1, 0); y <= Math.min(i + 1, m - 1); y++){ for(int x = Math.max(j - 1, 0); x <= Math.min(j + 1, n - 1); x++){ // 累加bit1的值 lives += board[y][x] & 1; } } // 若是本身是活的,周邊有兩個活的,lives是3 // 若是本身是死的,周邊有三個活的,lives是3 // 若是本身是活的,周邊有三個活的,lives減本身是3 if(lives == 3 || lives - board[i][j] == 3){ board[i][j] |= 2; } } } // 右移就是新的值 for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ board[i][j] >>>= 1; } } } }