289. 生命游戏
题目:
思路:
【1】依靠辅助空间,将变更的状态记录到辅助空间则不会干扰到原本的数组
【2】增加变更状态,因为哪怕是状态变更了,也要确保能够识别变更之前的状态,不然记录的结果会不准确
代码展示:
//时间0 ms 击败 100% //内存39.8 MB 击败 42.19% //时间复杂度:O(mn),其中 m 和 n 分别为 board 的行数和列数。 //空间复杂度:O(mn),为复制数组占用的空间。 class Solution { public void gameOfLife(int[][] board) { // 八个位置的偏移量 int[][] positionArr = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}}; int maxRow = board.length; int maxCol = board[0].length; int tagRow = 0, tagCol = 0; // 设置结果数组 int[][] result = new int[maxRow][maxCol]; // 对结果数组进行初始化 for (int[] re : result){ Arrays.fill(re,0); } // 从上往下遍历 for (int i = 0; i < maxRow; i++){ // 从左往右遍历 for (int j = 0; j < maxCol; j++){ // 开始统计当前位置的周边情况 // 活细胞个数 int livingCellNum = 0; // 遍历周边八个位置 for (int[] p : positionArr){ tagRow = p[0] + i; tagCol = p[1] + j; // 出现越界的情况则跳过 if (tagRow >= 0 && tagCol>= 0 && tagRow < maxRow && tagCol < maxCol){ // 如果是活细胞则要记录 if (board[tagRow][tagCol] == 1) livingCellNum++; } } // 根据活细胞个数判断 // 如果活细胞个数是3,活的会保留,死的会复活,故是1 if (livingCellNum == 3) result[i][j] = 1; // 如果活细胞个数是2,活的会保留 if (livingCellNum == 2 && board[i][j] == 1) result[i][j] = 1; //其余情况活细胞会死亡,死亡细胞就不用管了 } } // 将结果覆盖回原数组 for (int i = 0; i < maxRow; i++){ // 从左往右遍历 for (int j = 0; j < maxCol; j++){ board[i][j] = result[i][j]; } } } } //时间0 ms 击败 100% //内存39.7 MB 击败 62.77% //时间复杂度:O(mn),其中 m,n 分别为 board 的行数和列数。 //空间复杂度:O(1),除原数组外只需要常数的空间存放若干变量。 //由于只是在原本的数组上增加变更状态最后进行复原所以空间复杂度是不会增加的 //而方向数组因为是固定值所以空间复杂度也是不会增加的 class Solution { public void gameOfLife(int[][] board) { // 八个位置的偏移量 int[][] positionArr = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}}; int maxRow = board.length; int maxCol = board[0].length; int tagRow = 0, tagCol = 0; // 因为要对原数组进行变更,所以对于要变更的状态为 // 0为原本死亡 , 1为原本存活,2为死亡变复活,-1为原本复活变死亡 // 从上往下遍历 for (int i = 0; i < maxRow; i++){ // 从左往右遍历 for (int j = 0; j < maxCol; j++){ // 开始统计当前位置的周边情况 // 活细胞个数 int livingCellNum = 0; // 遍历周边八个位置 for (int[] p : positionArr){ tagRow = p[0] + i; tagCol = p[1] + j; // 出现越界的情况则跳过 if (tagRow >= 0 && tagCol>= 0 && tagRow < maxRow && tagCol < maxCol){ // 如果是活细胞则要记录 // (不管是原本就是活的,还是由活得变为死亡的,原本都算是活得) if (Math.abs(board[tagRow][tagCol]) == 1) livingCellNum++; } } // 根据活细胞个数判断 // 如果活细胞个数是3,活的会保留,死的会复活(即变为2) if (livingCellNum == 3 && board[i][j] == 0) board[i][j] = 2; // 其余导致原本存活的细胞变为死亡的情况 if ((board[i][j] == 1) && (livingCellNum < 2 || livingCellNum > 3)) { // -1 代表这个细胞过去是活的现在死了 board[i][j] = -1; } } } // 将结果覆盖回原数组 for (int i = 0; i < maxRow; i++){ // 从左往右遍历 for (int j = 0; j < maxCol; j++){ if (board[i][j] > 0) { board[i][j] = 1; } else { board[i][j] = 0; } } } } }