題目
在一個 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’
解法一(行列查找)
思路:查找到白色車所在的座標後,依次提取出對應的行列,然後在裏面進行查找。
- 提取白色車所在的行列座標
- 獲取白色車對應行和列的值,組成新的列表
- 在兩個列表中判斷和計算
- 時間複雜度: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
解法二(遞歸查找)
思路:得到白色車所在行列後,以該位置爲中心分別進行遞歸查找
- 提取白色車所在的行列座標
- 使用遞歸在對應方向上持續尋找,直到邊界
- 分別計算前後左右四個不同的方向
- 時間複雜度: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
解法三(方向數組)
思路:基本原理跟解法二一致,使用方向數組進行循環查找
- 提取白色車所在的行列座標
- 使用方向數組,在四個方向上分別進行循環,每次僅在一個方向上前進
- 累計四個方向的判斷結果
- 時間複雜度: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