leetcode 289. Game of Life
来源:互联网 发布:四川长虹人工智能 编辑:程序博客网 时间:2024/06/08 06:32
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."
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):
- Any live cell with fewer than two live neighbors dies, as if caused by under-population.
- Any live cell with two or three live neighbors lives on to the next generation.
- Any live cell with more than three live neighbors dies, as if by over-population..
- Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
Follow up:
- Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
- In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
为了在原有的数组空间中解决该问题,我们使用 2 bits 来存储 4 个状态:
[2nd bit, 1st bit] = [next state, current state]- 00 dead (next) <- dead (current) 状态0:死->死- 01 dead (next) <- live (current) 状态1:活->死- 10 live (next) <- dead (current) 状态2:死->活- 11 live (next) <- live (current) 状态3:活->活
要得到 board[i][j] 的当前状态,只需要如下操作。奇数 代表当前状态是 活的,偶数 代表当前状态是 死的。
board[i][j] % 2
要得到 board[i][j] 的下一个状态,只需要如下操作。≥2 代表下一状态是 活的,<2 代表下一状态是 死的。
board[i][j] / 2
//活->活=3 活->死=1//死->死=0 死->活=2public void gameOfLife(int[][] board) {if(board.length==0||board[0].length==0){return;}int m=board.length;int n=board[0].length;for(int i=0;i<m;i++){for(int j=0;j<n;j++){int liveNeighbors=getLiveCells(board, m, n, i, j);//Any live cell with fewer than two live neighbors dies.//Any live cell with two or three live neighbors lives.//Any live cell with more than three live neighbors dies.//Any dead cell with exactly three live neighbors becomes a live cell.if(board[i][j]%2==1){ //如果当前cell是活着的if(liveNeighbors<2||liveNeighbors>3){board[i][j]=1; //活->死}else{board[i][j]=3; //活->活}}else{ //如果当前cel是死着的if(liveNeighbors==3){board[i][j]=2; //死->活}else{board[i][j]=0; //死->死}}}}for(int i=0;i<m;i++){for(int j=0;j<n;j++){board[i][j]=board[i][j]/2;}}return;}public int getLiveCells(int[][] board,int m,int n,int i,int j){int count=0;int[][] directions=new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};for(int c=0;c<8;c++){int x=i+directions[c][0];int y=j+directions[c][1];if(x<0||x>=m||y<0||y>=n){continue;}if(board[x][y]%2==1){count++;}}return count;}
对于follow-up问题中的:In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
大神表示:Instead of 使用 1,0 二维数组,而是使用 live cell 坐标集合 来表示该 board。
在 set 中存放的是所有活着的细胞的坐标集合。那么如何计算 活着的邻居个数 呢?可以遍历 live cell 集合,然后增加它们邻居的计数器(所以那些没有活着邻居的细胞将不会出现在这个计数器中)。最后,我们通过提取那些拥有正确数量活着邻居的细胞,来放入新的 live cell 集合。
private Set<Coord> getNewLives(Set<Coord> live) { Map<Coord,Integer> neighbours = new HashMap<>(); for (Coord cell : live) { for (int i = cell.i-1; i<cell.i+2; i++) { for (int j = cell.j-1; j<cell.j+2; j++) { if (i==cell.i && j==cell.j) continue; Coord c = new Coord(i,j); if (neighbours.containsKey(c)) { neighbours.put(c, neighbours.get(c) + 1); } else { neighbours.put(c, 1); } } } } Set<Coord> newLive = new HashSet<>(); for (Map.Entry<Coord,Integer> cell : neighbours.entrySet()) { if (cell.getValue() == 3 || cell.getValue() == 2 && live.contains(cell.getKey())) { newLive.add(cell.getKey()); } } return newLive; }
where Coord is:
private static class Coord { int i; int j; private Coord(int i, int j) { this.i = i; this.j = j; } public boolean equals(Object o) { return o instanceof Coord && ((Coord)o).i == i && ((Coord)o).j == j; } public int hashCode() { int hashCode = 1; hashCode = 31 * hashCode + i; hashCode = 31 * hashCode + j; return hashCode; } }
and the wrapper:
public void gameOfLife(int[][] board) { Set<Coord> live = new HashSet<>(); int m = board.length; int n = board[0].length; for (int i = 0; i<m; i++) { for (int j = 0; j<n; j++) { if (board[i][j] == 1) { live.add(new Coord(i,j)); } } }; live = getNewLives(live); for (int i = 0; i<m; i++) { for (int j = 0; j<n; j++) { board[i][j] = live.contains(new Coord(i,j))?1:0; } }; }
- [leetcode] 289. Game of Life
- 289. Game of Life LeetCode
- leetcode 289. Game of Life
- [LeetCode]289. Game of Life
- LeetCode 289. Game of Life
- LeetCode *** 289. Game of Life
- 【leetcode】289. Game of Life
- LeetCode 289. Game of Life
- LeetCode-289.Game of Life
- [Leetcode]289. Game of Life
- LeetCode--289. Game of Life
- [leetcode] 289. Game of Life
- [LeetCode] 289. Game of Life
- [leetcode]289. Game of Life
- [LeetCode]289. Game of Life
- [LeetCode]289. Game of Life
- 【LeetCode】 289. Game of Life
- LeetCode 289. Game of Life
- chosen.jquery
- jquery数据处理
- arm 基础知识分享
- JavaWeb——Servlet开发
- mysql 存储,更新 时间戳转换成timestamp格式
- leetcode 289. Game of Life
- Java 枚举(enum)入门学习
- 《最大子序列的分析》
- Hibernate 实体级联配置(one-to-one,many-to-one,many-to-many)
- ffmpeg批量转换wav到MP3
- UDP协议及URL
- jquery属性过滤器
- C/C++安全编程规范及一些代码静态安全检测工具
- HTML5调用照相机并自定义显示获取到的图片(FileReader)