1、題目編程
一、審題spa
二、分析code
編程實現 「LIFE」 這個遊戲:blog
①、若 m 的周圍8個鄰居細胞中存活的細胞數 < 2,則此細胞從存活狀態變爲死亡狀態;遊戲
②、若 m 的周圍8個鄰居細胞中存活的細胞數 = 2 或 = 3,則此細胞從存活狀態變爲存活狀態;ip
③、若 m 的周圍8個鄰居細胞中存活的細胞數 > 3,則此細胞從存活狀態變爲死亡狀態;it
③、若 m 的周圍8個鄰居細胞中存活的細胞數 = 3,則此細胞從死亡狀態變爲存活狀態; io
只能一次性更新全部的細胞的狀態,不能用改變後的狀態來判斷後邊的細胞的狀態。class
其中 1表明存活狀態,0 表明死亡狀態。循環
2、解答
一、思路
方法1、
①、採用兩個 bit 位來表示狀態。剛開始,全部細胞所有是 00 或者 01;
②、注意狀態 1 與狀態 2 是獨立的。
③、全部的細胞是同時從狀態 1 變爲狀態 2的。
④、計算全部細胞在未變化以前的全部鄰居細胞的狀態,並記錄此細胞將要變化的狀態2。
⑤、由於狀態 2 默認爲 0,即死亡狀態,故不須要考慮狀態轉變: 01 --> 00
⑥、最終,經過 >> 1 向右移動一位,刪除全部細胞的狀態 1.
⑦、每個細胞的狀態 2 的計算方法:
01 --> 11: 當 board == 1 而且 2 <= lives && lives <= 3;
00 --> 10: 當 board == 0 而且 lives == 3。
⑧、獲取當前的細胞的狀態: board[i][j] & 1
⑨、獲取細胞將要變化的狀態: board[i][j] >> 1
1 public void gameOfLife(int[][] board) { 2 if(board == null || board.length == 0) 3 return; 4 int m = board.length, n = board[0].length; 5 6 // In the beginning, every 2nd bit is 0; 7 // So we only need to care about when will the 2nd bit become 1. 8 for(int i = 0; i < m; i++) { 9 for (int j = 0; j < n; j++) { 10 int lives = liveNeighbors(board, m, n, i, j); 11 if(board[i][j] == 1 && 2 <= lives && lives <= 3) 12 board[i][j] = 3; // Make the 2nd bit 1: 01 ---> 11 13 if(board[i][j] == 0 && lives == 3) 14 board[i][j] = 2; // Make the 2nd bit 1: 00 ---> 10 15 } 16 } 17 18 for(int i = 0; i < m; i++) 19 for (int j = 0; j < n; j++) 20 board[i][j] >>= 1; 21 } 22 23 private int liveNeighbors(int[][] board, int m, int n, int i, int j) { 24 int lives = 0; 25 for(int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) { 26 for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) { 27 lives += board[x][y] & 1; 28 } 29 } 30 lives -= board[i][j] & 1; 31 return lives; 32 }
方法2、
能夠經過值不是 0 和 1 的兩個常量記錄此細胞將要變化的狀態。
從而不影響統計出其餘細胞的周圍的存活細胞數。
最終在循環給元素賦更新的值。
1 int live = 3; 2 int die = 2; 3 public void gameOfLife2(int[][] board) { 4 if(board == null || board.length == 0) 5 return; 6 int rows = board.length, cols = board[0].length; 7 // we only flip the 1 to die and 0 to live 8 // so when we find a die around, it must be a previous 1 9 // then we can count the 1s without being affected 10 for (int i = 0; i < rows; i++) { 11 for (int j = 0; j < cols; j++) { 12 int around = countLive(i, j, board); 13 if(board[i][j] == 0 && around == 3) 14 board[i][j] = live; 15 else if(board[i][j] == 1) { 16 if(around == 2 || around == 3) 17 continue; 18 if(around < 2 || around > 3) 19 board[i][j] = die; 20 } 21 } 22 } 23 for (int i=0;i<rows;i++){ 24 for (int j=0;j<cols;j++){ 25 if (board[i][j] == die) 26 board[i][j] = 0; 27 if (board[i][j] == live) 28 board[i][j] = 1; 29 } 30 } 31 } 32 33 private int countLive(int i, int j, int[][] board) { 34 int count = 0; 35 int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}}; 36 37 for (int[] dir:dirs){ 38 int x = i+dir[0]; 39 int y = j+dir[1]; 40 41 if (x>=0 && y>=0 && x < board.length && y<board[0].length ){ 42 43 if (board[x][y] == 1 || board[x][y] == die) 44 count ++; 45 } 46 } 47 48 return count; 49 }