news 2026/5/29 0:50:20

LeetCode LeetCode 2801. 统计范围内的步进数字数目 C++实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode LeetCode 2801. 统计范围内的步进数字数目 C++实现

这道题是经典的数位 DP(Digit DP)问题。我们可以直接沿用之前 Java 实现的记忆化搜索思路,将其转化为 C++ 代码。

核心思路
1. 前缀和思想:将求解闭区间 [low, high] 转化为 count(high) - count(low - 1)。
2. 记忆化搜索(DFS):
* 使用 dfs(pos, prevDigit, isLimit, isNum) 从高位向低位枚举。
* pos:当前遍历到的数位下标。
* prevDigit:上一位填入的数字(用于判断相邻数位差的绝对值是否为 1)。
* isLimit:当前位是否受上界字符串的限制。
* isNum:前面是否已经填入了非零的有效数字(用于处理前导 0)。
3. 字符串减一操作:由于 low 和 high 的长度可达 100,必须使用字符串来模拟大数减 1 的操作,以避免整数溢出。

C++ 代码实现

#include <vector>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;

class Solution {
private:
static const int MOD = 1000000007;
string s;
// 记忆化数组:[位置][上一位数字(0-9)][是否受限制][前面是否已填数字]
// 上一位数字用 10 表示初始状态(前面没有数字)
int memo[105][11][2][2];

// 字符串模拟数字减 1(处理 low - 1,避免大数溢出)
string subtractOne(string str) {
int i = str.length() - 1;
// 从最后一位开始借位
while (i >= 0 && str[i] == '0') {
str[i] = '9';
i--;
}
// 如果还没减完(比如 1000 -> 0999)
if (i >= 0) {
str[i]--;
}
// 去掉前导 0
if (str[0] == '0' && str.length() > 1) {
return str.substr(1);
}
return str;
}

// 计算从 0 到字符串 s 代表的数字之间有多少个步进数字
long long dfs(int pos, int prevDigit, bool isLimit, bool isNum) {
// 递归终止条件:已经填完所有位置
if (pos == s.length()) {
// 如果前面填了有效数字,说明找到了一个合法的步进数字
return isNum ? 1 : 0;
}

// 如果该状态已经计算过,直接返回
if (memo[pos][prevDigit][isLimit][isNum] != -1) {
return memo[pos][prevDigit][isLimit][isNum];
}

long long res = 0;
// 确定当前位能填入的最大数字
int up = isLimit ? s[pos] - '0' : 9;

// 1. 处理前导 0 的情况:如果前面还没填数字,当前位可以继续填 0(跳过)
if (!isNum) {
res = (res + dfs(pos + 1, 10, false, false)) % MOD;
}

// 2. 枚举当前位填入的数字 d
// 起始数字:如果前面没填数字(!isNum),从1开始;否则从0开始
int start = isNum ? 0 : 1;
for (int d = start; d <= up; d++) {
// 如果前面已经填了数字,需要满足步进条件:相邻数字差的绝对值为 1
if (isNum && abs(d - prevDigit) != 1) {
continue;
}
// 递归进入下一位
res = (res + dfs(pos + 1, d, isLimit && d == up, true)) % MOD;
}

// 记录并返回结果
memo[pos][prevDigit][isLimit][isNum] = res;
return res;
}

long long count(string str) {
s = str;
// 初始化记忆化数组为 -1
memset(memo, -1, sizeof(memo));
return dfs(0, 10, true, false);
}

public:
int countSteppingNumbers(string low, string high) {
// 计算 [0, high] 的步进数字个数
long long countHigh = count(high);
// 计算 [0, low-1] 的步进数字个数
long long countLow = count(subtractOne(low));

// 结果为两者之差,注意取模防止负数
return (int)((countHigh - countLow + MOD) % MOD);
}
};

复杂度分析
* 时间复杂度:O(log N),其中 N 是 high 的数值。数位 DP 的状态数取决于数字的位数(最多 100 位)、上一位数字(0-9,共11种状态)、是否受限(2种)和是否已填数字(2种)。总状态数非常少,每次转移最多枚举 10 个数字,因此效率极高。
* 空间复杂度:O(log N),主要用于存储记忆化搜索的 memo 数组以及递归调用的栈空间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/29 0:50:18

Qwen Max LeetCode 2809. 使数组和小于等于 x 的最少时间 Go实现

哈哈&#xff0c;又来啦&#xff01;看来你真的很喜欢 Go 版本&#xff0c;或者正在用 Go 刷题&#xff5e;没问题&#xff01;这次我给你一个**极致清晰、防坑、带注释、可直接 AC** 的 Go 实现&#xff0c;并且把关键逻辑再强化一遍&#xff0c;保证你不仅会写&#xff0c;还…

作者头像 李华
网站建设 2026/5/29 0:50:00

5分钟搞定网易云音乐插件安装:BetterNCM Installer完全指南

5分钟搞定网易云音乐插件安装&#xff1a;BetterNCM Installer完全指南 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 你是否曾经因为网易云音乐功能不够丰富而烦恼&#xff1f;或者想…

作者头像 李华
网站建设 2026/5/29 0:49:23

深度评测2026年TOP10降AI率网站:只选真正管用的那一款!

随着AI技术的不断进步&#xff0c;越来越多的学生和职场人士开始依赖AI写作工具来提升论文撰写和内容创作的效率。然而&#xff0c;这种便捷的背后也带来了新的挑战——各大高校、期刊以及平台对AI生成内容的检测标准日益严格&#xff0c;许多用户发现&#xff0c;自己精心撰写…

作者头像 李华
网站建设 2026/5/29 0:47:19

鱼眼相机人体检测

要求在鱼眼相机下检测出图像中的人&#xff0c;不想标注图像&#xff0c;不想微调&#xff0c;就想用点现成的。先找了个专门检测鱼眼相机人体检测的开源项目&#xff0c;然后有尝试了yolov8-obb&#xff0c;yolov11等&#xff0c;最后尝试了SAM3&#xff0c;还是SAM3效果好。这…

作者头像 李华
网站建设 2026/5/29 0:46:21

剪映自动化革命:Python如何让视频剪辑进入程序化时代

剪映自动化革命&#xff1a;Python如何让视频剪辑进入程序化时代 【免费下载链接】JianYingApi Third Party JianYing Api. 第三方剪映Api 项目地址: https://gitcode.com/gh_mirrors/ji/JianYingApi 你是否曾想象过&#xff0c;用代码就能控制专业级视频剪辑软件&#…

作者头像 李华
网站建设 2026/5/29 0:43:09

07-WebGL 的“Hello World“:绘制第一个三角形

WebGL 的"Hello World":绘制第一个三角形 知识点1:三角形是图形学的基础图元 📖 为什么是三角形? 在计算机图形学中,三角形是构建所有复杂3D模型的基础单元。任何复杂的几何体(立方体、球体、角色模型、地形)都可以分解为无数个三角形。 三角形的独特优势…

作者头像 李华