如何用记忆化递归高效计算满足长度约束的二进制字符串数量

小明君_5447

小明君_5447

2026-07-01

854人浏览

原创

如何用记忆化递归高效计算满足长度约束的二进制字符串数量

本文讲解如何将暴力生成字符串的指数级解法优化为时间复杂度 O(high) 的记忆化递归方案,核心是放弃构造字符串,转而定义 dp[k] 为恰好长度为 k 的合法字符串数量,并利用子问题重叠进行缓存。

本文讲解如何将暴力生成字符串的指数级解法优化为时间复杂度 o(high) 的记忆化递归方案,核心是放弃构造字符串,转而定义 `dp[k]` 为恰好长度为 k 的合法字符串数量,并利用子问题重叠进行缓存。

该问题本质是一个计数型动态规划问题:从空串出发,每次只能追加 zero 个 '0' 或 one 个 '1'(即长度分别增加 zero 或 one),求最终长度落在 [low, high] 区间内的所有不同字符串总数。

原始代码的问题在于:

  • 实际拼接字符串(如 s + a),时间和空间开销巨大;
  • 未去重且反复计算相同长度的子问题(例如多次计算“长度为 2 的方案数”);
  • 递归无记忆,导致时间复杂度呈指数级增长(TLE)。

✅ 正确思路是:只关心字符串长度,不关心具体内容。
定义状态:
dp[k] = 恰好构成长度为 k 的合法字符串的方案总数。

状态转移方程:

  • 若当前长度为 k,它可能由长度 k - zero 的串末尾加 zero 个 '0' 得到;
  • 也可能由长度 k - one 的串末尾加 one 个 '1' 得到。
    因此:
    dp[k] = dp[k - zero] + dp[k - one]

    边界条件:dp[0] = 1(空串是一种方案),对 k

    ViiTor AI
    ViiTor AI

    ViiTor AI是一款面向视频翻译、配音、口型同步和多语言内容本地化的 AI 视频工具。

    下载

使用记忆化(如哈希表或数组缓存)避免重复计算。推荐用数组 dp[0..high],初始化 dp[0] = 1,其余为 0,正向递推更清晰:

public int countGoodStrings(int low, int high, int zero, int one) {
    int[] dp = new int[high + 1];
    dp[0] = 1; // 空串为唯一基础方案

    for (int len = 1; len = zero) dp[len] = (dp[len] + dp[len - zero]) % 1_000_000_007;
        if (len >= one)  dp[len] = (dp[len] + dp[len - one])  % 1_000_000_007;
    }

    int ans = 0;
    for (int len = low; len <p>⚠️ 注意事项:</p>
  • 必须对结果取模 10^9+7(题目隐含要求,防止整数溢出);
  • dp 数组大小为 high + 1,确保覆盖所有可能长度;
  • 转移时需判断 len >= zero/one,避免数组越界;
  • 不要混淆“恰好长度 k”与“长度 ≤ k”——本题需对 [low, high] 区间内所有 dp[len] 求和。

该解法时间复杂度 O(high),空间复杂度 O(high),彻底规避了字符串构造与重复计算,是典型“状态抽象 + 记忆化/递推”的优化范式。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1618

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2404

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

5884

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

5149

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

6874

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

9494

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

4819

17

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.07

5087

13

常用字符串方法大全
常用字符串方法大全

常用字符串方法大全

2025.08.08

2628

14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习