3種解法 - 得到國際象棋中車的可用捕獲量


題目

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

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

返回車能夠在一次移動中捕獲到的卒的數量。

示例 1:
在這裏插入圖片描述

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

示例 2:

在這裏插入圖片描述

輸入:[[".",".",".",".",".",".",".","."],[".",“p”,“p”,“p”,“p”,“p”,".","."],[".",“p”,“p”,“B”,“p”,“p”,".","."],[".",“p”,“B”,“R”,“B”,“p”,".","."],[".",“p”,“p”,“B”,“p”,“p”,".","."],[".",“p”,“p”,“p”,“p”,“p”,".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
輸出:0
解釋:
象阻止了車捕獲任何卒。

提示:

board.length == board[i].length == 8
board[i][j] 可以是 ‘R’,’.’,‘B’ 或 ‘p’
只有一個格子上存在 board[i][j] == ‘R’


解法一(行列查找)

思路:查找到白色車所在的座標後,依次提取出對應的行列,然後在裏面進行查找。

  1. 提取白色車所在的行列座標
  2. 獲取白色車對應行和列的值,組成新的列表
  3. 在兩個列表中判斷和計算
  • 時間複雜度:O(n2)
  • 空間複雜度:O(n)
class Solution:    
    def numRookCaptures(self, board: List[List[str]]) -> int:
        row,col , cnt = -1,-1,0
        lenRow, lenCol = len(board), len(board[0])
        #獲取座標位置
        for i in range(0,lenRow):
            if 'R' in board[i]:
                col = board[i].index('R')
                row = i
                break
        #子函數判斷是否滿足
        def checkP(bList, start, end, direct)-> int:
            for i in range(start,end,direct):
                if bList[i] == 'p':
                    return 1
                elif bList[i] == 'B':
                    return 0
            return 0
        #提取行列
        rowList = board[row]
        colList = [b[col] for b in board]
        #依次判斷
        cnt += checkP(colList,row-1,-1,-1)
        cnt += checkP(colList,row+1,lenRow,1)
        cnt += checkP(rowList,col-1,-1,-1)
        cnt += checkP(rowList,col+1,lenCol,1)
        return cnt

解法二(遞歸查找)

思路:得到白色車所在行列後,以該位置爲中心分別進行遞歸查找

  1. 提取白色車所在的行列座標
  2. 使用遞歸在對應方向上持續尋找,直到邊界
  3. 分別計算前後左右四個不同的方向
  • 時間複雜度:O(n2)
  • 空間複雜度:O(1)
class Solution:    
    def numRookCaptures(self, board: List[List[str]]) -> int:
        row,col , cnt = -1,-1,0
        lenRow, lenCol = len(board), len(board[0])
        #獲取座標位置
        for i in range(0,lenRow):
            if 'R' in board[i]:
                col = board[i].index('R')
                row = i
                break
        # 在一個方向上遞歸查找
        def checkP(rIdx, cIdx, rDelta, cDelta, lenList)-> int:
            if not( 0 <= rIdx < lenList and 0 <= cIdx < lenList):
                return 0
            if board[rIdx][cIdx] == 'p':
                return 1
            elif board[rIdx][cIdx] == 'B':
                return 0
            else :
                return checkP(rIdx + rDelta,cIdx + cDelta,rDelta,cDelta,lenList)
        # 四個方向分別計算
        cnt += checkP(row+1,col,1,0,lenRow)
        cnt += checkP(row,col+1,0,1,lenRow)
        cnt += checkP(row-1,col,-1,0,lenRow)
        cnt += checkP(row,col-1,0,-1,lenRow)
        return cnt
        

解法三(方向數組)

思路:基本原理跟解法二一致,使用方向數組進行循環查找

  1. 提取白色車所在的行列座標
  2. 使用方向數組,在四個方向上分別進行循環,每次僅在一個方向上前進
  3. 累計四個方向的判斷結果
  • 時間複雜度:O(n2)
  • 空間複雜度:O(1)
class Solution:    
    def numRookCaptures(self, board: List[List[str]]) -> int:
        row,col , cnt = -1,-1,0
        lenRow, lenCol = len(board), len(board[0])
        dirRow, dirCol = [1,0,-1,0],[0,1,0,-1]
        for i in range(0,lenRow):
            if 'R' in board[i]:
                col = board[i].index('R')
                row = i
                break
        for i in range(0,4):#4個方向
            rIdx, cIdx = row, col
            for j in range(0,lenRow):
                rIdx += dirRow[i]
                cIdx += dirCol[i]
                if not( 0 <= rIdx < lenRow and 0 <= cIdx < lenRow):
                    break
                if board[rIdx][cIdx] == 'p':
                    cnt += 1
                    break
                elif board[rIdx][cIdx] == 'B':
                    break
        return cnt        
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章