Leetcode 289 - Game of Life(array)

24 篇文章 0 订阅

github仓库:https://github.com/lzed/leetcode

题意

给出一个矩阵的一个状态,根据一定规则来计算下一个状态。

思路

算法1

O(mn) 的额外空间。

新开一个数组来获得下一个状态即可,这样可以保证状态互不干扰。

算法2

O(1) 额外空间, O(mn) 时间。

要更新一个位置 (i,j) 的时候,我们需要知道它的neibor的状态,但是neibor的状态可能已经被更新过,但是我们依赖的是以前的状态,然后最后的结果统计又依赖于最后的状态。即又依赖于之前的状态,又依赖于之后的状态,那么我们就可以建立一个状态转化的映射:

f(x,y)=s :分别代表之前状态是x,转化为一个新的状态y,我们用s代表其接结果。

那么,一共只有4种转化(1代表Live,0代表dead)

f(0,0)=2

f(0,1)=3

f(1,0)=4

f(1,1)=5

于是,在对 (i,j) 进行状态更新时,我们可以通过上面的转换表得到它周围的更新/未更新位置的初始状态。

最后统计结果的时候,我们再对上述关系进行逆映射来得到最后结果。

代码

algorithm 1

class Solution {
public:
    int judge(int x, int y, vector<vector<int>>& a) {
        int cnt = 0;
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (!i && !j) continue;
                int nx = x + i, ny = y + j;
                if (nx >= 0 && nx < a.size() && ny >= 0 && ny < a[0].size()) {
                    if (a[nx][ny]) cnt++;
                }
            }
        }    
        return cnt;
    }

    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        if (m) {
            int n = board[0].size();
            vector<vector<int>> a(board.size(), vector<int>(n));
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    int t = judge(i, j, board);
                    if (board[i][j]) {
                        if (t < 2) a[i][j] = 0;
                        else if (t == 2 || t == 3) a[i][j] = 1;
                        else a[i][j] = 0;
                    } else {
                        if (t == 3) a[i][j] = 1;
                        else a[i][j] = 0;
                    }
                }
            }
            board = a;
        }
    }
};

algorithm 2

class Solution {
public:
    int f(int x, int y) {
        if (!x && !y) return 2;
        if (!x && y) return 3;
        if (x && !y) return 4;
        return 5;
    }

    int g_pre(int s) {
        if (s == 1 || s == 0) return s;
        if (s == 2 || s == 3) return 0;
        return 1;
    }

    int g_now(int s) {
        if (s == 1 || s == 0) return s;
        if (s == 2 || s == 4) return 0;
        return 1;
    }

    int judge(int x, int y, vector<vector<int>>& a) {
        int cnt = 0;
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (!i && !j) continue;
                int nx = x + i, ny = y + j;
                if (nx >= 0 && nx < a.size() && ny >= 0 && ny < a[0].size()) {
                    if (g_pre(a[nx][ny])) cnt++;
                }
            }
        }    
        return cnt;
    }

    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        if (m) {
            int n = board[0].size();
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    int t = judge(i, j, board);
                    if (board[i][j]) {
                        if (t < 2 || t >= 4) board[i][j] = f(1, 0);
                        else board[i][j] = f(1, 1);
                    } else {
                        if (t == 3) board[i][j] = f(0, 1);
                        else board[i][j] = f(0, 0);
                    }
                }
            }
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++)
                    board[i][j] = g_now(board[i][j]);
            }
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值