<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?LeetCode刷題實戰(zhàn)289:生命游戲

          共 7355字,需瀏覽 15分鐘

           ·

          2021-06-12 21:49

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎知識和業(yè)務邏輯面試+算法面試。所以,為了提高大家的算法能力,這個公眾號后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

          今天和大家聊的問題叫做 生命游戲,我們先來看題面:
          https://leetcode-cn.com/problems/game-of-life/


          根據(jù) 百度百科 ,生命游戲,簡稱為生命,是英國數(shù)學家約翰·何頓·康威在 1970 年發(fā)明的細胞自動機。

          給定一個包含 m × n 個格子的面板,每一個格子都可以看成是一個細胞。每個細胞都具有一個初始狀態(tài):1 即為活細胞(live),或 0 即為死細胞(dead)。每個細胞與其八個相鄰位置(水平,垂直,對角線)的細胞都遵循以下四條生存定律:

          • 如果活細胞周圍八個位置的活細胞數(shù)少于兩個,則該位置活細胞死亡;

          • 如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;

          • 如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡;

          • 如果死細胞周圍正好有三個活細胞,則該位置死細胞復活;



          下一個狀態(tài)是通過將上述規(guī)則同時應用于當前狀態(tài)下的每個細胞所形成的,其中細胞的出生和死亡是同時發(fā)生的。給你 m x n 網(wǎng)格面板 board 的當前狀態(tài),返回下一個狀態(tài)。

          示例


          解題

          https://leetcode-cn.com/problems/game-of-life/solution/sheng-ming-you-xi-by-leetcode-solution/

          使用額外的狀態(tài)

          題目中每個細胞只有兩種狀態(tài) live(1) 或 dead(0),但我們可以拓展一些復合狀態(tài)使其包含之前的狀態(tài)。舉個例子,如果細胞之前的狀態(tài)是 0,但是在更新之后變成了 1,我們就可以給它定義一個復合狀態(tài) 2。這樣我們看到 2,既能知道目前這個細胞是活的,還能知道它之前是死的。

          算法

          遍歷 board 中的細胞。

          根據(jù)數(shù)組的細胞狀態(tài)計算新一輪的細胞狀態(tài),這里會用到能同時代表過去狀態(tài)和現(xiàn)在狀態(tài)的復合狀態(tài)。

          具體的計算規(guī)則如下所示:

          規(guī)則 1:如果活細胞周圍八個位置的活細胞數(shù)少于兩個,則該位置活細胞死亡。這時候,將細胞值改為 -1,代表這個細胞過去是活的現(xiàn)在死了;

          規(guī)則 2:如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活。這時候不改變細胞的值,仍為 1;

          規(guī)則 3:如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡。這時候,將細胞的值改為 -1,代表這個細胞過去是活的現(xiàn)在死了??梢钥吹?,因為規(guī)則 1 和規(guī)則 3 下細胞的起始終止狀態(tài)是一致的,因此它們的復合狀態(tài)也一致;

          規(guī)則 4:如果死細胞周圍正好有三個活細胞,則該位置死細胞復活。這時候,將細胞的值改為 2,代表這個細胞過去是死的現(xiàn)在活了。

          根據(jù)新的規(guī)則更新數(shù)組;

          現(xiàn)在復合狀態(tài)隱含了過去細胞的狀態(tài),所以我們可以在不復制數(shù)組的情況下完成原地更新;

          對于最終的輸出,需要將 board 轉(zhuǎn)成 0,1 的形式。因此這時候需要再遍歷一次數(shù)組,將復合狀態(tài)為 2 的細胞的值改為 1,復合狀態(tài)為 -1 的細胞的值改為 0。

          class Solution {
              public void gameOfLife(int[][] board) {
                  int[] neighbors = {0, 1, -1};

                  int rows = board.length;
                  int cols = board[0].length;

                  // 遍歷面板每一個格子里的細胞
                  for (int row = 0; row < rows; row++) {
                      for (int col = 0; col < cols; col++) {

                          // 對于每一個細胞統(tǒng)計其八個相鄰位置里的活細胞數(shù)量
                          int liveNeighbors = 0;

                          for (int i = 0; i < 3; i++) {
                              for (int j = 0; j < 3; j++) {

                                  if (!(neighbors[i] == 0 && neighbors[j] == 0)) {
                                      // 相鄰位置的坐標
                                      int r = (row + neighbors[i]);
                                      int c = (col + neighbors[j]);

                                      // 查看相鄰的細胞是否是活細胞
                                      if ((r < rows && r >= 0) && (c < cols && c >= 0) && (Math.abs(board[r][c]) == 1)) {
                                          liveNeighbors += 1;
                                      }
                                  }
                              }
                          }

                          // 規(guī)則 1 或規(guī)則 3
                          if ((board[row][col] == 1) && (liveNeighbors < 2 || liveNeighbors > 3)) {
                              // -1 代表這個細胞過去是活的現(xiàn)在死了
                              board[row][col] = -1;
                          }
                          // 規(guī)則 4
                          if (board[row][col] == 0 && liveNeighbors == 3) {
                              // 2 代表這個細胞過去是死的現(xiàn)在活了
                              board[row][col] = 2;
                          }
                      }
                  }

                  // 遍歷 board 得到一次更新后的狀態(tài)
                  for (int row = 0; row < rows; row++) {
                      for (int col = 0; col < cols; col++) {
                          if (board[row][col] > 0) {
                              board[row][col] = 1;
                          } else {
                              board[row][col] = 0;
                          }
                      }
                  }
              }
          }


          好了,今天的文章就到這里,如果覺得有所收獲,請順手點個在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動力 。

          上期推文:

          LeetCode1-280題匯總,希望對你有點幫助!
          LeetCode刷題實戰(zhàn)281:鋸齒迭代器
          LeetCode刷題實戰(zhàn)282:給表達式添加運算符
          LeetCode刷題實戰(zhàn)283:移動零
          LeetCode刷題實戰(zhàn)284:頂端迭代器
          LeetCode刷題實戰(zhàn)285:二叉搜索樹中的順序后繼
          LeetCode刷題實戰(zhàn)286:墻和門
          LeetCode刷題實戰(zhàn)287:尋找重復數(shù)
          LeetCode刷題實戰(zhàn)288:單詞的唯一縮寫


          瀏覽 75
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青五月丁香在线 | 亚洲天堂在线播放 | 色色影院精品 | 免费看黄色片视频 | 久久久久国产一级毛片高 |