返回
C/C++ 2320. 统计放置房子的方式数:初学者指南
后端
2024-01-22 14:07:48
LeetCode 2320. 统计放置房子的方式数 是一道经典的排列组合问题,它要求我们计算在给定的土地上建造一排房屋的不同方式。这道题对于初学者来说很有挑战性,但掌握了解决这类问题的基本方法至关重要。本文将提供逐步指南,引导你轻松理解题目,掌握解题思路,并编写出高效的代码。
题目
一块土地上有一些空地,你可以在这块土地上建造房屋。土地可以被划分为若干个连续的空地块,每个空地块只能建造一栋房子。给你这块土地的宽度 width
,其中 0
表示空地,1
表示房屋。请你计算建造一排房屋的不同方式。
示例:
- 输入:
width = "00000"
- 输出:
9
题目整理
输入:
width
:一个长度为n
的字符串,其中0
表示空地,1
表示房屋。
输出:
int
:建造一排房屋的不同方式。
解题思路
这道题本质上是一个排列组合问题,我们可以将土地划分为 n
个空地块,然后计算在这些空地块中放置 k
栋房屋的不同方式。具体来说,我们可以使用动态规划的方法解决这个问题:
- 状态定义:
dp[i][k]
表示前i
个空地块中放置k
栋房屋的不同方式。 - 状态转移方程:
- 若
width[i] == '0'
,则dp[i][k] = dp[i-1][k] + dp[i-1][k-1]
。 - 若
width[i] == '1'
,则dp[i][k] = dp[i-1][k]
。
- 若
- 初始化:
dp[0][0] = 1
dp[i][0] = dp[i-1][0]
- 最终结果:
dp[n][k]
具体实现
class Solution {
public:
int countHousePlacements(string width) {
int n = width.size();
int mod = 1e9 + 7;
vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
dp[i][0] = dp[i - 1][0];
for (int j = 1; j <= n; j++) {
if (width[i - 1] == '0') {
dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % mod;
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][n];
}
};
代码分析
- 我们定义了一个二维数组
dp
,其中dp[i][k]
表示前i
个空地块中放置k
栋房屋的不同方式。 - 我们首先初始化
dp[0][0]
为 1,因为只有一个空地块,放置 0 栋房屋只有一种方式。 - 接下来,我们遍历所有空地块
i
和放置的房屋数量k
。 - 若当前空地块
width[i - 1]
为0
,则我们可以放置或不放置房屋。若放置房屋,则转移到状态dp[i - 1][k - 1]
。若不放置房屋,则转移到状态dp[i - 1][k]
。 - 若当前空地块
width[i - 1]
为1
,则只能不放置房屋,转移到状态dp[i - 1][k]
。 - 最后,我们返回
dp[n][n]
,即在所有空地块中放置n
栋房屋的不同方式。
复杂度分析
- 时间复杂度:O(n2),其中 n 是空地块的数量。
- 空间复杂度:O(n2),其中 n 是空地块的数量。
结语
通过本文,你掌握了解决 LeetCode 2320 的基本方法,并学会了编写高效的代码。在实践中,尝试解决类似的排列组合问题,进一步提升你的解题能力。通过不断练习,你将成为解决算法问题的专家。