You have two types of tiles: a 2 x 1
domino shape and a tromino shape. You may rotate these shapes.
Given an integer n, return the number of ways to tile an 2 x n
board. Since the answer may be very large, return it modulo 10<sup>9</sup> + 7
.
In a tiling, every square must be covered by a tile. Two tilings are different if and only if there are two 4-directionally adjacent cells on the board such that exactly one of the tilings has both squares occupied by a tile.
Example 1:
Input: n = 3 Output: 5 Explanation: The five different ways are shown above.
Example 2:
Input: n = 1 Output: 1
Constraints:
1 <= n <= 1000
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
For the domino and tromino tiling problem, the brute force approach means we try to fill a grid of a given length with tiles by trying all possible placements. It's like physically experimenting with the tiles to see all the ways they can fit.
Here's how the algorithm would work step-by-step:
def domino_and_tromino_tiling_brute_force(grid_length):
total_tilings = 0
modulo = 10**9 + 7
def solve(current_length):
nonlocal total_tilings
if current_length == grid_length:
# Found a valid tiling, increment the count
total_tilings = (total_tilings + 1) % modulo
return
if current_length > grid_length:
return
# Try placing a vertical domino
solve(current_length + 1)
# Try placing a horizontal domino
solve(current_length + 2)
# Try placing trominos in all four orientations
# These cover the cases where there are L-shaped placements
solve(current_length + 2)
solve(current_length + 3)
solve(current_length + 3)
solve(current_length + 3)
solve(0)
return total_tilings
This problem is about figuring out the best way to cover a board using dominoes (two squares) and trominoes (three squares). The most efficient way is to break down the problem into smaller, repeatable steps by figuring out how many ways you can cover the board for each length.
Here's how the algorithm would work step-by-step:
def domino_and_tromino_tiling(board_length):
modulo = 10**9 + 7
# Handle base cases for boards of length 1, 2, and 3.
if board_length <= 2:
if board_length == 1:
return 1
return board_length
number_of_ways = [0] * (board_length + 1)
number_of_ways[0] = 1
number_of_ways[1] = 1
number_of_ways[2] = 2
# Maintain counts of partial tromino coverings.
partial_tromino_coverings = [0] * (board_length + 1)
partial_tromino_coverings[0] = 0
partial_tromino_coverings[1] = 0
partial_tromino_coverings[2] = 2
for i in range(3, board_length + 1):
# Vertical domino from i-1 or horizontal domino pair from i-2.
number_of_ways[i] = (number_of_ways[i - 1] + number_of_ways[i - 2]) % modulo
# Add the ways trominoes cover, trominoes contribute 2*ways[i-3].
number_of_ways[i] = (number_of_ways[i] + 2 * number_of_ways[i - 3]) % modulo
return number_of_ways[board_length]
Case | How to Handle |
---|---|
n = 0 | Return 1, as there's one way to tile an empty board (do nothing). |
n = 1 | Return 1, as a single domino can be placed vertically to fill the 2x1 board. |
n = 2 | Return 2, as two vertical dominoes or two horizontal dominoes can tile the 2x2 board. |
Large n leading to integer overflow | Apply the modulo operator (10^9 + 7) after each calculation to prevent integer overflow. |
Very large n (e.g., n > 10^6) | Ensure the solution's time complexity is O(n) or better, such as using dynamic programming or a matrix exponentiation approach to avoid timeouts. |
Negative n | Return 0, since tiling a board with negative length is not possible. |
All tilings are Tromino tilings | The DP solution will still consider all possibilities and correctly count such scenarios. |
Edge cases in the recurrence relation calculation (e.g., indexing at n-1, n-2, n-3) | Initialize the base cases of the DP table (for n=0, n=1, n=2, n=3) to avoid out-of-bounds errors or incorrect computations. |