leetcode 289 生命遊戲
阿新 • • 發佈:2018-11-16
根據百度百科,生命遊戲,簡稱為生命,是英國數學家約翰·何頓·康威在1970年發明的細胞自動機。
給定一個包含 m × n 個格子的面板,每一個格子都可以看成是一個細胞。每個細胞具有一個初始狀態 live(1)即為活細胞, 或 dead(0)即為死細胞。每個細胞與其八個相鄰位置(水平,垂直,對角線)的細胞都遵循以下四條生存定律:
- 如果活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡;
- 如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;
- 如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡;
- 如果死細胞周圍正好有三個活細胞,則該位置死細胞復活;
根據當前狀態,寫一個函式來計算面板上細胞的下一個(一次更新後的)狀態。下一個狀態是通過將上述規則同時應用於當前狀態下的每個細胞所形成的,其中細胞的出生和死亡是同時發生的。
示例:
輸入: [ [0,1,0], [0,0,1], [1,1,1], [0,0,0] ] 輸出: [ [0,0,0], [1,0,1], [0,1,1], [0,1,0] ]
進階:
- 你可以使用原地演算法解決本題嗎?請注意,面板上所有格子需要同時被更新:你不能先更新某些格子,然後使用它們的更新後的值再更新其他格子。
- 本題中,我們使用二維陣列來表示面板。原則上,面板是無限的,但當活細胞侵佔了面板邊界時會造成問題。你將如何解決這些問題?
思路:
要求是使用原地演算法,所以新開一個數組進行計算的方法就不考慮了。
因此,我們要將board[i][j]改變之前和改變之後的狀態記錄下來。可以發現一共有4種情況:
- 0 -> 0
- 1 -> 1
- 0 -> 1
- 1 -> 0
前兩種情況沒有發生狀態的改變,可以不管。對於後兩種情況,0->1時,可將board[i][j]=2,1->0時,將board[i][j]=3,這樣就可以知道board[i][j]改變之前和改變之後的狀態了。最後再將狀態2、3改回對應的1、2狀態即可。
class Solution {
int[] dx= new int[]{-1,0,1};
int[] dy= new int[]{-1,0,1};
int m,n;
boolean check(int x,int y,int[][] board){
int cnt=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(dx[i]==0&&dy[j]==0)continue;
int nx=x+dx[i];
int ny=y+dy[j];
if(nx<0||nx>=m||ny<0||ny>=n) continue;
if(board[nx][ny]==1||board[nx][ny]==3)cnt++;
}
}
if(board[x][y]==1&&(cnt<2||cnt>3)) return true;
if(board[x][y]==0&&cnt==3)return true;
return false;
}
public void gameOfLife(int[][] board) {
m=board.length;
n=board[0].length;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(check(i,j,board)){
board[i][j]+=2;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(board[i][j]==2)board[i][j]=1;
if(board[i][j]==3)board[i][j]=0;
}
}
}
}