Facebook Pixel

999. Available Captures for Rook

EasyArrayMatrixSimulation
Leetcode Link

Problem Description

You have an 8×8 chessboard represented as a matrix with the following pieces:

  • One white rook represented by 'R'
  • Some white bishops represented by 'B'
  • Some black pawns represented by 'p'
  • Empty squares represented by '.'

A rook can move any number of squares in four directions: horizontally (left/right) or vertically (up/down). The rook continues moving until it:

  • Reaches another piece (bishop or pawn)
  • Reaches the edge of the board

The rook is attacking a pawn if it can reach the pawn's square in a single move. However, the rook cannot move through other pieces - if a bishop or another pawn blocks the path, the rook cannot attack pawns beyond that blocking piece.

Your task is to count how many black pawns the white rook can attack from its current position.

Example scenarios:

  • If there's a pawn directly in line with the rook (horizontally or vertically) with no pieces between them, the rook can attack it
  • If there's a bishop between the rook and a pawn, the rook cannot attack that pawn
  • The rook can potentially attack up to 4 pawns (one in each direction: up, down, left, right)
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that a rook attacks in straight lines - up, down, left, and right. From the rook's position, we need to check what the first piece is in each of these four directions.

Think of it like shining a laser beam from the rook in each direction. The beam travels in a straight line until it hits something:

  • If it hits a pawn ('p'), we can capture it, so we count it
  • If it hits a bishop ('B'), it blocks our path and we can't see beyond it
  • If it hits an empty square ('.'), we keep looking further in that direction
  • If it reaches the board edge, we stop looking in that direction

This naturally leads us to a simulation approach: find the rook's position first, then "walk" in each of the four directions from that position. For each direction, we keep moving square by square until we either:

  1. Find a pawn (increment our count and stop looking in this direction)
  2. Find a bishop (stop looking in this direction without counting)
  3. Reach the board boundary (stop looking in this direction)

The direction vectors (-1, 0), (1, 0), (0, -1), (0, 1) represent moving up, down, left, and right respectively. By using dirs = (-1, 0, 1, 0, -1) and pairing consecutive elements, we get these four direction vectors elegantly.

The maximum number of pawns we can attack is 4 (one in each direction), and the minimum is 0 (if all directions are blocked by bishops or empty).

Solution Approach

The implementation follows a systematic simulation approach:

Step 1: Find the Rook's Position We traverse the entire 8×8 board using nested loops to locate the white rook 'R'. Once found at position (i, j), we can begin checking for attackable pawns.

Step 2: Set Up Direction Vectors We use dirs = (-1, 0, 1, 0, -1) to represent the four directions. By using pairwise(dirs), we get the direction pairs:

  • (-1, 0): Move up (decrease row)
  • (0, 1): Move right (increase column)
  • (1, 0): Move down (increase row)
  • (0, -1): Move left (decrease column)

Step 3: Explore Each Direction For each direction (a, b):

  1. Start from the rook's adjacent square: x, y = i + a, j + b
  2. Continue moving in that direction while:
    • We're within board boundaries: 0 <= x < n and 0 <= y < n
    • We haven't encountered a bishop: board[x][y] != "B"
  3. During this traversal:
    • If we find a pawn board[x][y] == "p", increment the answer and stop exploring this direction
    • If we find an empty square '.', continue to the next square: x, y = x + a, y + b

Step 4: Return the Count After exploring all four directions, return the total number of pawns that can be attacked.

The algorithm has a time complexity of O(n²) for finding the rook, plus O(n) for exploring each direction, resulting in overall O(n²) where n = 8. The space complexity is O(1) as we only use a few variables to track position and count.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Consider this 8×8 board:

. . . . . . . .
. . . p . . . .
. B . R . . . .
. . . . . . . .
. . . p . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .

Step 1: Find the Rook We scan the board and find the rook 'R' at position (2, 3).

Step 2: Explore Each Direction

Direction 1: Up (-1, 0)

  • Start at (2, 3) and move up to (1, 3)
  • We find a pawn 'p' at (1, 3)
  • Count = 1, stop exploring this direction

Direction 2: Right (0, 1)

  • Start at (2, 3) and move right to (2, 4)
  • Empty square '.', continue to (2, 5)
  • Empty square '.', continue to (2, 6)
  • Empty square '.', continue to (2, 7)
  • Reached board edge, stop exploring
  • No pawns found in this direction

Direction 3: Down (1, 0)

  • Start at (2, 3) and move down to (3, 3)
  • Empty square '.', continue to (4, 3)
  • We find a pawn 'p' at (4, 3)
  • Count = 2, stop exploring this direction

Direction 4: Left (0, -1)

  • Start at (2, 3) and move left to (2, 2)
  • Empty square '.', continue to (2, 1)
  • We find a bishop 'B' at (2, 1)
  • Bishop blocks the path, stop exploring
  • No pawns found in this direction

Final Answer: 2

The rook can attack 2 pawns - one directly above and one directly below. The bishop to the left blocks that direction, and there are no pieces to the right.

Solution Implementation

1class Solution:
2    def numRookCaptures(self, board: List[List[str]]) -> int:
3        # Define four directions: up, right, down, left
4        # Using pairwise iteration: (-1,0), (0,1), (1,0), (0,-1)
5        directions = (-1, 0, 1, 0, -1)
6        board_size = len(board)
7      
8        # Find the rook's position on the board
9        for row in range(board_size):
10            for col in range(board_size):
11                if board[row][col] == "R":
12                    captured_pawns = 0
13                  
14                    # Check all four directions from the rook
15                    for i in range(4):
16                        # Get direction vector using pairwise
17                        dx = directions[i]
18                        dy = directions[i + 1]
19                      
20                        # Start from the rook's adjacent cell in current direction
21                        current_row = row + dx
22                        current_col = col + dy
23                      
24                        # Continue moving in the same direction until hitting a boundary or bishop
25                        while 0 <= current_row < board_size and 0 <= current_col < board_size and board[current_row][current_col] != "B":
26                            # If we find a pawn, capture it and stop in this direction
27                            if board[current_row][current_col] == "p":
28                                captured_pawns += 1
29                                break
30                          
31                            # Move to the next cell in the same direction
32                            current_row += dx
33                            current_col += dy
34                  
35                    return captured_pawns
36
1class Solution {
2    public int numRookCaptures(char[][] board) {
3        // Direction vectors: up, right, down, left
4        // Using pairs (dx, dy) stored consecutively: (-1,0), (0,1), (1,0), (0,-1)
5        final int[] DIRECTIONS = {-1, 0, 1, 0, -1};
6      
7        int boardSize = board.length;
8      
9        // Find the white rook on the board
10        for (int row = 0; row < boardSize; row++) {
11            for (int col = 0; col < boardSize; col++) {
12                if (board[row][col] == 'R') {
13                    int capturedPawns = 0;
14                  
15                    // Check all 4 directions from the rook
16                    for (int dir = 0; dir < 4; dir++) {
17                        // Get direction offsets for current direction
18                        int deltaRow = DIRECTIONS[dir];
19                        int deltaCol = DIRECTIONS[dir + 1];
20                      
21                        // Start from the position next to the rook
22                        int currentRow = row + deltaRow;
23                        int currentCol = col + deltaCol;
24                      
25                        // Move in the current direction until hitting a boundary, bishop, or pawn
26                        while (currentRow >= 0 && currentRow < boardSize && 
27                               currentCol >= 0 && currentCol < boardSize && 
28                               board[currentRow][currentCol] != 'B') {
29                          
30                            // Check if we found a black pawn to capture
31                            if (board[currentRow][currentCol] == 'p') {
32                                capturedPawns++;
33                                break; // Stop searching in this direction after capturing
34                            }
35                          
36                            // Move to the next position in the same direction
37                            currentRow += deltaRow;
38                            currentCol += deltaCol;
39                        }
40                    }
41                  
42                    return capturedPawns;
43                }
44            }
45        }
46      
47        // No rook found on the board (shouldn't happen in valid input)
48        return 0;
49    }
50}
51
1class Solution {
2public:
3    int numRookCaptures(vector<vector<char>>& board) {
4        // Direction vectors: up, right, down, left
5        // Using pairs: (-1,0), (0,1), (1,0), (0,-1)
6        const int directions[5] = {-1, 0, 1, 0, -1};
7        int boardSize = board.size();
8      
9        // Find the white rook on the board
10        for (int row = 0; row < boardSize; ++row) {
11            for (int col = 0; col < boardSize; ++col) {
12                if (board[row][col] == 'R') {
13                    int captureCount = 0;
14                  
15                    // Check all 4 directions from the rook's position
16                    for (int dir = 0; dir < 4; ++dir) {
17                        // Get direction deltas for current direction
18                        int deltaRow = directions[dir];
19                        int deltaCol = directions[dir + 1];
20                      
21                        // Start from the next cell in current direction
22                        int currentRow = row + deltaRow;
23                        int currentCol = col + deltaCol;
24                      
25                        // Keep moving in the current direction until hitting a boundary or bishop
26                        while (currentRow >= 0 && currentRow < boardSize && 
27                               currentCol >= 0 && currentCol < boardSize && 
28                               board[currentRow][currentCol] != 'B') {
29                          
30                            // If we find a black pawn, capture it and stop in this direction
31                            if (board[currentRow][currentCol] == 'p') {
32                                ++captureCount;
33                                break;
34                            }
35                          
36                            // Move to the next cell in the same direction
37                            currentRow += deltaRow;
38                            currentCol += deltaCol;
39                        }
40                    }
41                  
42                    return captureCount;
43                }
44            }
45        }
46      
47        // Return 0 if no rook found (edge case)
48        return 0;
49    }
50};
51
1/**
2 * Counts the number of pawns that a rook can capture on a chess board
3 * @param board - 8x8 chess board where 'R' is rook, 'B' is bishop, 'p' is pawn, '.' is empty
4 * @returns Number of pawns the rook can capture
5 */
6function numRookCaptures(board: string[][]): number {
7    // Direction vectors for moving up, right, down, left
8    const directions: number[] = [-1, 0, 1, 0, -1];
9    const boardSize: number = board.length;
10  
11    // Find the rook on the board
12    for (let row = 0; row < boardSize; row++) {
13        for (let col = 0; col < boardSize; col++) {
14            if (board[row][col] === 'R') {
15                let captureCount: number = 0;
16              
17                // Check all 4 directions from the rook's position
18                for (let dirIndex = 0; dirIndex < 4; dirIndex++) {
19                    let currentRow: number = row + directions[dirIndex];
20                    let currentCol: number = col + directions[dirIndex + 1];
21                  
22                    // Move in the current direction until hitting a boundary or bishop
23                    while (currentRow >= 0 && currentRow < boardSize && 
24                           currentCol >= 0 && currentCol < boardSize && 
25                           board[currentRow][currentCol] !== 'B') {
26                      
27                        // If we find a pawn, increment count and stop in this direction
28                        if (board[currentRow][currentCol] === 'p') {
29                            captureCount++;
30                            break;
31                        }
32                      
33                        // Continue moving in the same direction
34                        currentRow += directions[dirIndex];
35                        currentCol += directions[dirIndex + 1];
36                    }
37                }
38              
39                return captureCount;
40            }
41        }
42    }
43  
44    // Return 0 if no rook found (edge case)
45    return 0;
46}
47

Time and Space Complexity

The time complexity is O(m × n), where m and n are the number of rows and columns of the board, respectively. In this problem, m = n = 8 (standard chess board size), making the actual complexity O(64) = O(1). The algorithm needs to traverse the entire board once to find the rook, which takes O(m × n) time. Once the rook is found, it explores in 4 directions (up, down, left, right), and in the worst case, each direction traverses at most n cells. Since there's only one rook on the board, the directional searches contribute O(4n) = O(n) time. The overall complexity remains O(m × n) as the board traversal dominates.

The space complexity is O(1). The algorithm only uses a constant amount of extra space for variables like dirs (which stores 5 integers), loop counters (i, j, x, y), and the answer counter ans. No additional data structures that scale with input size are created.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Direction Vector Usage

The code uses directions = (-1, 0, 1, 0, -1) with index-based access to get direction pairs. A common mistake is misunderstanding how this works or incorrectly accessing the pairs.

Pitfall Example:

# Wrong: Using wrong indices or not understanding the pairwise concept
dx = directions[i]
dy = directions[i + 1]  # This works but can be confusing

Better Solution:

# More explicit and readable approach
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]  # up, right, down, left
for dx, dy in directions:
    current_row = row + dx
    current_col = col + dy
    # ... rest of the logic

2. Breaking After Finding Any Piece

A critical mistake is breaking the loop when encountering ANY piece, not just pawns.

Pitfall Example:

while 0 <= current_row < board_size and 0 <= current_col < board_size:
    if board[current_row][current_col] != '.':  # Wrong! This stops at bishops too
        if board[current_row][current_col] == 'p':
            captured_pawns += 1
        break  # This would count bishops as stopping points, not blocking pieces

Correct Approach:

while 0 <= current_row < board_size and 0 <= current_col < board_size:
    piece = board[current_row][current_col]
    if piece == 'B':  # Bishop blocks the path
        break
    if piece == 'p':  # Found a pawn to capture
        captured_pawns += 1
        break
    # Continue if it's an empty square '.'
    current_row += dx
    current_col += dy

3. Not Stopping After Finding the Rook

Once the rook is found and processed, the function should return immediately. Continuing to search wastes time and could cause errors if there were multiple rooks (though the problem guarantees only one).

Pitfall Example:

for row in range(board_size):
    for col in range(board_size):
        if board[row][col] == "R":
            # Process rook...
            # Missing return statement here!
# This would continue searching even after finding the rook
return captured_pawns  # Wrong scope - captured_pawns might not be defined here

Correct Approach:

for row in range(board_size):
    for col in range(board_size):
        if board[row][col] == "R":
            # Process all four directions
            # ...
            return captured_pawns  # Return immediately after processing the rook
return 0  # Safety return if no rook found (shouldn't happen per problem constraints)

4. Confusing Bishop Blocking Logic

The while loop condition board[current_row][current_col] != "B" checks the current position AFTER moving. This could lead to array index errors.

Pitfall Example:

# This checks the position after moving, which might be out of bounds
while 0 <= current_row < board_size and 0 <= current_col < board_size and board[current_row][current_col] != "B":
    # If current_row or current_col is out of bounds, 
    # the board access happens before the bounds check in some languages

Safer Approach:

while 0 <= current_row < board_size and 0 <= current_col < board_size:
    if board[current_row][current_col] == "B":
        break  # Stop if we hit a bishop
    if board[current_row][current_col] == "p":
        captured_pawns += 1
        break  # Stop after capturing a pawn
    current_row += dx
    current_col += dy
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which two pointer techniques do you use to check if a string is a palindrome?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More