LeetCode - 999. 車的可用捕獲量 - 方向數組思想

LeetCode 999. 車的可用捕獲量 - 方向數組思想

問題描述:

在一個 8 x 8 的棋盤上,有一個白色車(rook)。也可能有空方塊,白色的象(bishop)和黑色的卒(pawn)。它們分別以字符 “R”,“.”,“B” 和 “p” 給出。大寫字符表示白棋,小寫字符表示黑棋。

車按國際象棋中的規則移動:它選擇四個基本方向中的一個(北,東,西和南),然後朝那個方向移動,直到它選擇停止、到達棋盤的邊緣或移動到同一方格來捕獲該方格上顏色相反的卒。另外,車不能與其他友方(白色)象進入同一個方格。

求解問題:
返回車能夠在一次移動中捕獲到的卒的數量。

在這裏插入圖片描述
輸入:[[".",".",".",".",".",".",".","."],[".",".",".",“p”,".",".",".","."],[".",".",".",“R”,".",".",".",“p”],[".",".",".",".",".",".",".","."],
[".",".",".",".",".",".",".","."],[".",".",".",“p”,".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
輸出:3
解釋:在本例中,車能夠捕獲所有的卒。

問題解決方案

1. 方案一(普通暴力法):

不優美的方式:

  1. 首先找到 “車” 這個棋的位置爲(2,3)
  2. 以車(2,3)的位置爲起點,分別向上下左右進行遍歷,判斷移動的位置是否爲 符合條件的卒。
    public int numRookCaptures(char[][] board) {
        int count = 0;
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
//              查找車的位置
                if (board[i][j] == 'R') {
                    //上
                    for (int l = j; l >= 0; l--) {
                        if (board[i][l] == 'B') {
                            break;
                        } else if (board[i][l] == 'p') {
                            count++;
                            break;
                        }
                    }
                    //下
                    for (int l = j; l < 8; l++) {
                        if (board[i][l] == 'B') {
                            break;
                        } else if (board[i][l] == 'p') {
                            count++;
                            break;
                        }
                    }
                    //左
                    for (int h = i; h >= 0; h--) {
                        if (board[h][j] == 'B') {
                            break;
                        } else if (board[h][j] == 'p') {
                            count++;
                            break;
                        }
                    }
                    //右
                    for (int h = i; h < 8; h++) {
                        if (board[h][j] == 'B') {
                            break;
                        } else if (board[h][j] == 'p') {
                            count++;
                            break;
                        }
                    }
                }
            }
        }
        return count;
    }

這種方式寫出來的代碼會出現四個重複的for循環,十分不優美。
遂經過思考與參看資料,發現對於這一類的網格類的問題,可以通過方向數組來優化移動問題,具體講解見方式二。

2. 方式二(優化):

通過方向數組的思想,優化方案一中的上下左右四個暴力遍歷的方式。

方向數組
我們看面圖的案例,車的位置爲(2,3),車向上移1格之後的座標爲(1,3),其實(1,3)的由來爲:(2,3) + (1,0)\color{red}(-1,0)
  同理,車向下移動一格之後的座標爲:(2,3) + (1,0)\color{red}(1,0) = (3,3)
  車向坐移動一格之後的座標爲:(2,3) + (0,1)\color{red}(0,-1) = (2,2)
  車向下移動一格之後的座標爲:(2,3) + (0,1)\color{red}(0,1) = (2,4)

我們可以定義兩個數組來模擬車移動的狀態:

//      定義方向數組
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};

優化之後的完整代碼:

package indi.pentiumcm.leetcode;

/**
 * @projName: algorithm
 * @packgeName: indi.pentiumcm.leetcode
 * @className: Q11
 * @author: pentiumCM
 * @email: [email protected]
 * @date: 2020/3/26 15:26
 * @describe: LeetCode 999. 車的可用捕獲量
 */
public class Q11 {

    public int numRookCapturesV2(char[][] board) {

        int len = board.length;
//      定義喫到卒的個數
        int count = 0;

//      定義方向數組
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};

//      查找車的位置
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < len; j++) {
                if (board[i][j] == 'R') {
//                  上下左右四個方向分別移動
                    for (int k = 0; k < 4; k++) {
                        int x = i, y = j;
                        while (true) {
//                          移動一步的增量:(-1, 0)-向上移動 1 格
                            x += dx[k];
                            y += dy[k];
//                          移動超出棋盤
                            if (x <= 0 || x >= 8 || y <= 0 || y >= 8) {
                                break;
                            }
//                          移動到白象的位置
                            else if (board[x][y] == 'B') {
                                break;
                            } else if (board[x][y] == 'p') {
                                count++;
                                break;
                            }
                        }
                    }
                    return count;
                }
            }
        }
        return 0;
    }

    public static void main(String[] args) {
        char[][] boards = {{'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', 'R', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'},
                {'.', '.', '.', '.', '.', '.', '.', '.'}};

        int num = new Q11().numRookCapturesV2(boards);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章