題意
有一個 8 × 8 8 \times 8 8 × 8 的棋盤,棋盤上的格子狀態以二維陣列 board \text{board} board 給出,其中 board [ r ] [ c ] \text{board}[r][c] board [ r ] [ c ] 表示棋盤上的格子 ( r , c ) (r, c) ( r , c ) 。棋盤上空格用 '.'
表示,白棋用 'W'
表示,黑棋用 'B'
表示。
每次落子時,可以選擇一個空格,將其變成自己的顏色(白色或黑色)。但是,只有當這個格子變成一條 好線段(good line) 的 端點 時,這個落子才是合法的。
好線段(good line) 是指一條包含 三個或更多格子(包含端點格子) 的線段,線段的兩個端點格子是 同一種顏色 ,而中間剩餘的格子是 另一種顏色 (線段上不能有任何空格子)。
給定兩個整數 r M o v e rMove r M o v e 和 c M o v e cMove c M o v e 以及一個字元 c o l o r color co l or ,表示你將要在 ( r M o v e , c M o v e ) (rMove, cMove) ( r M o v e , c M o v e ) 這個格子上落子,且你執棋的顏色是 c o l o r color co l or 。請判斷這個操作是否合法,如果合法,返回 true \text{true} true ,否則返回 false \text{false} false 。
思路:枚舉所有方向
由於在合法操作時,落子點是一條好線段(good line) 的端點,因此可以透過枚舉所有方向,檢查在 ( r M o v e , c M o v e ) (rMove, cMove) ( r M o v e , c M o v e ) 位置落子後,是否存在一條 好線段(good line) 來判斷落子是否合法。
使用一個函數 check(dx, dy)
來檢查從 ( r M o v e , c M o v e ) (rMove, cMove) ( r M o v e , c M o v e ) 開始,沿著方向 ( d x , d y ) (dx, dy) ( d x , d y ) 是否能形成合法的線段。在檢查過程中,如果遇到了與落子顏色相同的格子,表示找到了另一個端點。如果中間至少有一個格子,則返回 true \text{true} true 表示找到了好線段。如果遇到了空格子,表示中間不連續,直接返回 false \text{false} false 。如果走出了棋盤範圍,則表示該方向上沒有找到好線段,同樣返回 false \text{false} false 。
枚舉所有方向時,可以使用雙重迴圈,分別枚舉 d x ∈ [ − 1 , 0 , 1 ] dx \in [-1, 0, 1] d x ∈ [ − 1 , 0 , 1 ] 和 d y ∈ [ − 1 , 0 , 1 ] dy \in [-1, 0, 1] d y ∈ [ − 1 , 0 , 1 ] ,但需要排除 d x = 0 dx = 0 d x = 0 且 d y = 0 dy = 0 d y = 0 的情況。對於每個方向呼叫 check(dx, dy)
函數,如果找到了好線段,則返回 true \text{true} true ,否則繼續檢查下一個方向。如果所有方向都沒有找到好線段,則返回 false \text{false} false 。
複雜度分析
時間複雜度:O ( max ( r , c ) ) O(\max(r, c)) O ( max ( r , c )) ,其中 r r r 和 c c c 分別是棋盤的 橫列(row) 和 直行(column) 數。
空間複雜度:O ( 1 ) O(1) O ( 1 ) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution : def checkMove (self, board: List [List [str ]], rMove: int , cMove: int , color: str ) -> bool : def check (dx, dy ): x, y = rMove + dx, cMove + dy cnt = 0 while 0 <= x < 8 and 0 <= y < 8 : if board[x][y] == color: return True if cnt > 0 else False if board[x][y] == "." : return False x += dx y += dy cnt += 1 return False for dx in range (-1 , 2 ): for dy in range (-1 , 2 ): if dx == 0 and dy == 0 : continue if check(dx, dy): return True return False
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : bool checkMove (vector<vector<char >>& board, int rMove, int cMove, char color) { function<bool (int , int )> check = [&](int dx, int dy) { int x = rMove + dx, y = cMove + dy; int cnt = 0 ; while (0 <= x && x < 8 && 0 <= y && y < 8 ) { if (board[x][y] == color) return cnt > 0 ; if (board[x][y] == '.' ) return false ; x += dx; y += dy; cnt++; } return false ; }; for (int dx = -1 ; dx <= 1 ; dx++) { for (int dy = -1 ; dy <= 1 ; dy++) { if (dx == 0 && dy == 0 ) continue ; if (check (dx, dy)) return true ; } } return false ; } };
寫在最後
Cover photo is remixed from @吃肥皂泡泡 , thanks for their work!