leetcode
leetcode 2251 ~ 2300
好二进制字符串的数量

好二进制字符串的数量

难度:

标签:

题目描述

代码结果

运行时间: 154 ms, 内存: 20.2 MB


// 题目思路:
// 这个题目要求找出所有满足特定条件的二进制字符串的数量。
// 条件为:字符串中没有连续的两个'0'。
// 使用Java Stream API我们可以简化一些操作,
// 但动态规划的核心思想仍然保持不变。
// 递推关系同样为:
// dp[i][0] = dp[i-1][1]
// dp[i][1] = dp[i-1][0] + dp[i-1][1]
// 初始化:dp[1][0] = 1, dp[1][1] = 1

import java.util.stream.IntStream;

public class Solution {
    public int countGoodBinaryStrings(int n) {
        if (n == 1) return 2;
        int[][] dp = new int[n + 1][2];
        dp[1][0] = 1;
        dp[1][1] = 1;
        IntStream.range(2, n + 1).forEach(i -> {
            dp[i][0] = dp[i - 1][1];
            dp[i][1] = dp[i - 1][0] + dp[i - 1][1];
        });
        return dp[n][0] + dp[n][1];
    }
}

解释

方法:

此题解采用动态规划的方法来解决“好二进制字符串的数量”问题。定义 dp[i] 表示长度为 i 的二进制字符串中满足条件的字符串数量。初始条件下,dp[0] = 1 表示长度为0的字符串(空字符串)是有效的。对于每个长度 i (从1到maxLength),若长度 i 大于等于 oneGroup,则可以在长度为 i-oneGroup 的所有好二进制字符串后附加 oneGroup 个 '1',形成新的好二进制字符串。类似地,若长度 i 大于等于 zeroGroup,则可以在长度为 i-zeroGroup 的所有好二进制字符串后附加 zeroGroup 个 '0'。最终结果为从 minLength 到 maxLength 的所有 dp 值的和,由于可能出现大数,结果需要对 MOD 取模。

时间复杂度:

O(maxLength)

空间复杂度:

O(maxLength)

代码细节讲解

🦆
在定义 dp[i] 时,为什么可以假定它仅依赖于 i-oneGroup 和 i-zeroGroup 的值,而不需要其他的组合或更复杂的依赖关系?
dp[i] 仅依赖于 i-oneGroup 和 i-zeroGroup 的值,因为题目要求计算的是由特定数量的连续 '1' 或连续 '0' 组成的二进制字符串的数量。这意味着,要形成一个长度为 i 的好二进制字符串,你只需要考虑在一个已经满足条件的较短字符串后附加指定数量的 '1' 或 '0'。因此,每个 dp[i] 只需基于长度为 i-oneGroup 和 i-zeroGroup 的好二进制字符串计算,无需考虑更复杂的组合或依赖关系。
🦆
当 oneGroup 和 zeroGroup 的值非常接近时,此动态规划解法对于重复计算的处理是如何优化的?
当 oneGroup 和 zeroGroup 值非常接近时,可能导致 dp[i-oneGroup] 和 dp[i-zeroGroup] 重复计算或近似相同的值。在题解中,通过累加 dp[i] = dp[i - oneGroup] 和 dp[i] = (dp[i] + dp[i - zeroGroup]) % MOD 来处理这种情况,确保每次更新都是有效的,并且通过模运算保持计算结果的稳定性。这样的处理方式虽然简单,但能够有效避免因重复或接近的值导致的计算过多。
🦆
在题解中没有明确提到'好二进制字符串'的具体定义,它是如何影响 dp 数组更新规则的?
题解中未明确‘好二进制字符串’的定义可能导致理解上的歧义,但根据题解的上下文,我们可以推断出‘好二进制字符串’指的是由连续的 '1' 组成的组和连续的 '0' 组成的组交替出现的字符串。这种特定的结构直接影响了 dp 数组的更新规则,即每次更新 dp[i] 时,只需考虑在有效的较短字符串后添加一组连续的 '1' 或 '0'。这反映了动态规划中的状态转移,仅通过添加连续的字符组来扩展已知的好字符串。
🦆
题解中提到需要对结果进行模运算(MOD = 10 ** 9 + 7),这里使用模运算的具体原因是什么?
在处理涉及大数的计算问题时,常常需要对结果进行模运算以防止整数溢出和降低计算结果的存储需求。MOD = 10 ** 9 + 7 是一个常用的大质数,用于模运算可以有效避免计算溢出,并且由于其是质数,也有助于在数学运算中保持良好的分布特性。在此题中,使用 MOD 进行模运算确保所有计算步骤中的数值都能够被有效管理且保持在一个安全的范围内,同时也保证最终结果的正确性。

相关问题