返回

C/C++ 2320. 统计放置房子的方式数:初学者指南

后端

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 的基本方法,并学会了编写高效的代码。在实践中,尝试解决类似的排列组合问题,进一步提升你的解题能力。通过不断练习,你将成为解决算法问题的专家。