You are given a 0-indexed binary string floor
, which represents the colors of tiles on a floor:
floor[i] = '0'
denotes that the ith
tile of the floor is colored black.floor[i] = '1'
denotes that the ith
tile of the floor is colored white.You are also given numCarpets
and carpetLen
. You have numCarpets
black carpets, each of length carpetLen
tiles. Cover the tiles with the given carpets such that the number of white tiles still visible is minimum. Carpets may overlap one another.
Return the minimum number of white tiles still visible.
Example 1:
Input: floor = "10110101", numCarpets = 2, carpetLen = 2 Output: 2 Explanation: The figure above shows one way of covering the tiles with the carpets such that only 2 white tiles are visible. No other way of covering the tiles with the carpets can leave less than 2 white tiles visible.
Example 2:
Input: floor = "11111", numCarpets = 2, carpetLen = 3 Output: 0 Explanation: The figure above shows one way of covering the tiles with the carpets such that no white tiles are visible. Note that the carpets are able to overlap one another.
Constraints:
1 <= carpetLen <= floor.length <= 1000
floor[i]
is either '0'
or '1'
.1 <= numCarpets <= 1000
This problem asks to find the minimum number of white tiles visible after covering some tiles with black carpets. We can solve this using dynamic programming with memoization.
Approach:
The core idea is to use a recursive function with memoization to explore all possible carpet placements. The function dfs(i, j)
represents the minimum number of visible white tiles starting from index i
in the floor
string and having j
carpets remaining.
Base Cases:
i
reaches the end of the floor
string (i >= n
), no more tiles need to be considered, so return 0.j == 0
), we can't cover any more tiles. We calculate the number of remaining white tiles from index i
to the end and return it. This is efficiently done using a pre-computed prefix sum array s
.Recursive Step:
floor[i]
is black ('0'), we can skip it and recursively call dfs(i + 1, j)
.dfs(i + 1, j)
.carpetLen
tiles, so we recursively call dfs(i + carpetLen, j - 1)
.Memoization:
dfs
function uses memoization (a cache, implemented differently in each language) to store the results of subproblems. This prevents redundant calculations and significantly improves efficiency.Prefix Sum:
s
is pre-calculated. s[i]
stores the total number of white tiles from index 0 to i - 1
. This allows us to quickly calculate the number of white tiles in a range using subtraction (s[end] - s[start]
).Time and Space Complexity:
floor
and m is numCarpets
. The memoization ensures that each state (i, j) is visited only once.s
uses O(n) space.Code Examples (with explanations):
The code implementations provided in Python, Java, C++, and Go follow the approach described above. The key differences are in the syntax and the specific implementation of memoization.
For example, in Python, @cache
is a decorator that automatically handles memoization. In Java and C++, we manually create and manage a 2D array f
as the memoization table. Go uses a similar manual approach. The prefix sum array calculation is similar across all languages. The recursive logic (dfs
function) remains consistent. The min
function is used to choose the best option (cover or don't cover) at each step.
This dynamic programming approach with memoization efficiently solves the problem by avoiding redundant computations and exploring all possible carpet placements to find the minimum number of visible white tiles.