当前位置: 首页 > news >正文

【数位dp】【动态规划】C++算法:233.数字 1 的个数

作者推荐

【动态规划】C++算法312 戳气球

本文涉及的基础知识点

动态规划 数位dp

LeetCode:233数字 1 的个数

给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
示例 1:
输入:n = 13
输出:6
示例 2:
输入:n = 0
输出:0
提示:
0 <= n <= 109

数位dp的封装类

本题比较简单,主要讲封装类。m_vPre记录上一位所有状态,程序结束时,记录的是最后一位的所有状态。
m_vPre是二维向量,一维长度4,分别表示4种边界状态,下标0记录 非上下界,下标1记录下界,下标2记录上界,3记录同时上下界。二维长度由构造函数的参数iResutlCount决定。ResultType类记录状态。

ELE枚举的元素类型
minEle元素最小值
maxEle元素最大值
pLower下界
pHigh上界
iNum上下界的长度

使用的时完成OnEnumFirstBit和OnEnumOtherBit,OnEnumFirstBit会不重复不遗漏的枚举第一位的 元素和边界状态。
OnEnumOtherBit,此函数会不重复不遗漏的依次枚举其它位的元素和边界状态。
只会枚举在范围内的状态,不会枚举非法状态。
pre和dp 是对应边界状态的状态,所以是一维向量。
注意 : 同一位 同一元素 同一状态 可能枚举两次,这不会造成重复计算。因为是两层枚举,第一层枚举:前一元素的边界状态;第二层枚举:当前元素。

template<class ELE, class ResultType, ELE minEle, ELE maxEle>
class CLowUperr
{
public:CLowUperr(int iResutlCount):m_iResutlCount(iResutlCount){}void Init(const ELE* pLower, const ELE* pHigh, int iNum){m_vPre.assign(4, vector<ResultType>(m_iResutlCount));if (iNum <= 0){return;}InitPre(pLower, pHigh);iNum--;while (iNum--){pLower++;pHigh++;vector<vector<ResultType>> dp(4, vector<ResultType>(m_iResutlCount));OnInitDP(dp);//处理非边界for (auto tmp = minEle; tmp <= maxEle; tmp++){OnEnumOtherBit(dp[0], m_vPre[0], tmp);}//处理下边界OnEnumOtherBit(dp[1], m_vPre[1], *pLower);for (auto tmp = *pLower + 1; tmp <= maxEle; tmp++){OnEnumOtherBit(dp[0], m_vPre[1], tmp );}//处理上边界OnEnumOtherBit(dp[2], m_vPre[2], *pHigh );for (auto tmp = minEle; tmp < *pHigh; tmp++){OnEnumOtherBit(dp[0], m_vPre[2], tmp );}//处理上下边界if (*pLower == *pHigh){OnEnumOtherBit(dp[3], m_vPre[3], *pLower);}else{OnEnumOtherBit(dp[1], m_vPre[3], *pLower );for (auto tmp = *pLower + 1; tmp < *pHigh; tmp++){OnEnumOtherBit(dp[0], m_vPre[3], tmp );}OnEnumOtherBit(dp[2], m_vPre[3], *pHigh );}m_vPre.swap(dp);}}/*ResultType Total(int iMinIndex, int iMaxIndex){ResultType ret;for (int status = 0; status < 4; status++){for (int index = iMinIndex; index <= iMaxIndex; index++){ret += m_vPre[status][index];}}return ret;}*/
protected:const int m_iResutlCount;void InitPre(const ELE* const pLower, const ELE* const pHigh){for (ELE cur = *pLower; cur <= *pHigh; cur++){int iStatus = 0;if (*pLower == cur){iStatus = *pLower == *pHigh ? 3 : 1;}else if (*pHigh == cur){iStatus = 2;}OnEnumFirstBit(m_vPre[iStatus], cur);}}virtual void OnEnumOtherBit(vector<ResultType>& dp, const vector<ResultType>& vPre, ELE curValue) = 0;virtual void OnEnumFirstBit(vector<ResultType>& vPre, const ELE curValue) = 0;virtual void OnInitDP(vector<vector<ResultType>>& dp){}vector<vector<ResultType>> m_vPre;
};

本题代码

核心代码

//pair<int, int> first记录在范围内符合要求的子串数量 second 记录1的数量
class CCharLowerUper : public CLowUperr<char, pair<int, int>, '0', '9'>
{
public:using CLowUperr<char, pair<int, int>, '0', '9'>::CLowUperr;int Total(int iMinIndex, int iMaxIndex){int ret = 0;		for (int index = iMinIndex; index <= iMaxIndex; index++){int cur = 0;for (int status = 0; status < 4; status++){cur += m_vPre[status][index].second;}ret += cur;std::cout << " index:" << index << " " << cur << std::endl;}return ret;}
protected:virtual void OnEnumFirstBit(vector<pair<int, int>>& vPre, const char curValue){const int index = curValue - '0';vPre[index].first =1 ;vPre[index].second = 1 == index;}virtual void OnEnumOtherBit(vector<pair<int,int>>& dp, const vector<pair<int, int>>& vPre, char curValue){const int index = curValue - '0';for (int i = 0; i < 10; i++){dp[index].first += vPre[i].first;dp[index].second += vPre[i].second;if (1 == index){dp[index].second += vPre[i].first;}}		}};
class Solution {
public:int countDigitOne(int n) {const string strN = std::to_string(n);const int len = strN.length();int iRet = 0;for (int i = 1; i < len; i++){CCharLowerUper lu(10);lu.Init(("1" + string(i - 1, '0')).c_str(),string(i,'9').c_str(),i);iRet += lu.Total(0, 9);}CCharLowerUper lu(10);lu.Init(("1" + string(len - 1, '0')).c_str(), strN.c_str(), len);iRet += lu.Total(0, 9);return iRet;}
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}
}int main()
{vector<int> nums;{Solution sln;int n = 30;auto res = sln.countDigitOne(n);Assert(13, res);}{Solution sln;int n=13;auto res = sln.countDigitOne(n);Assert(6, res);}{Solution sln;int n = 0;auto res = sln.countDigitOne(n);Assert(0, res);}}

2023年1月版

class Solution {
public:
int countDigitOne(int n) {
int iNum = 0;
int iMul = 1;
for (int i = 0; i < 9; i++)
{
iNum += n / (iMul * 10) *iMul;
int tmp = n % (iMul * 10);
if (tmp >= iMul)
{
if (tmp >= iMul * 2)
{
tmp = iMul * 2 - 1;
}
iNum += tmp - (iMul - 1);
}
iMul *= 10;
}
if (1000 * 1000 * 1000 == n)
{
iNum++;
}
return iNum;
}
};

2023年8月

class CTest : public CLowUperr<char,int,‘0’,‘9’>
{
public:
CTest():CLowUperr(10)
{
}
// 通过 CLowUperr 继承
virtual void OnDo(vector<vector>& dp, int preStatus, int curStatus, int cur) override
{
dp[curStatus][cur] += m_vPreCan[preStatus];
m_vCurOneNum[curStatus] += m_vPreOneNum[preStatus];
}
virtual void OnInitDP(vector<vector>& dp)
{
for (int i = 0; i < 4; i++)
{
m_vPreCan[i] = std::accumulate(MACRO_BEGIN_END(m_vPre[i]), 0);
m_vPreOneNum[i] = m_vCurOneNum[i] + m_vPre[i][1];
}
memset(m_vCurOneNum, 0, sizeof(m_vCurOneNum));
}
int Total()
{
int iRet = 0;
for (int i = 0; i < 4; i++)
{
iRet += m_vCurOneNum[i] + m_vPre[i][1];
}
return iRet;
}
int m_vPreCan[4] = { 0 };//前四中状态的可能
int m_vPreOneNum[4] = { 0 };//前面4种状态1的数量
int m_vCurOneNum[4] = { 0 };//前面4种状态1的数量
};

class Solution {
public:
int countDigitOne(int n) {
string str = std::to_string(n);
int len = 1;
for (; len < str.length(); len++)
{
Do(“1” + string(len - 1, ‘0’), string(len, ‘9’));
}
Do(“1” + string(len - 1, ‘0’), str);
return m_iRet;
}
void Do(string s1, string s2)
{
CTest test;
test.Init(s1.data(), s2.data(), s1.length());
m_iRet += test.Total();
}
int m_iRet;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 **C+

+17**
如无特殊说明,本算法用**C++**实现。

相关文章:

【数位dp】【动态规划】C++算法:233.数字 1 的个数

作者推荐 【动态规划】C算法312 戳气球 本文涉及的基础知识点 动态规划 数位dp LeetCode:233数字 1 的个数 给定一个整数 n&#xff0c;计算所有小于等于 n 的非负整数中数字 1 出现的个数。 示例 1&#xff1a; 输入&#xff1a;n 13 输出&#xff1a;6 示例 2&#xff…...

docker (portainer 安装nginx)

汉化版步骤可以参考&#xff1a;写文章-CSDN创作中心https://mp.csdn.net/mp_blog/creation/editor/135258056 一、创建容器 二、配置端口&#xff0c;以及容器卷挂载 挂载目录配置&#xff1a;(下方截图的目录如下&#xff0c;docker 改为 mydocker&#xff0c;用docker作为根…...

10个linux文件管理命令

1. ls – 列出目录内容 ls可能是每个Linux用户在其终端中键入的第一个命令。它允许您列出您想要的目录的内容&#xff08;默认情况下是当前目录&#xff09;&#xff0c;包括文件和其他嵌套目录。 它有很多选择&#xff0c;所以最好使用 --help 来获得一些帮助。此标志返回所…...

实战:使用docker容器化服务与文件挂载-2

接着上文&#xff0c;演示Elasticsearch 和 Kibana 的安装&#xff0c;并讲解文件挂载 Elasticsearch of Docker &#xff08;Kibana&#xff09; 1、Elasticsearch 安装 ElasticSearch 使用 Docker 安装&#xff1a;https://www.yuque.com/zhangshuaiyin/guli-mall/dwrp5b 1.…...

联合union

//————联合&#xff1a;union 1.联合的定义 联合也是一种特殊的自定义类型 #include<stdio.h> union Un//Un为联合标签 { int a; char c; }; struct St { int a; int b; }; int main() { union Un u; printf("%d\n",sizeof(u));//…...

如何在 Umi /Umi 4.0 中配置自动删除 console.log 语句?

背景&#xff0c;开发时需要console.log 日志&#xff0c;再生产、uat 、sit不想看到日志打印信息 方案1、代码规范eslint校验"no-console": true, //console.log 方案2、bable 插件 babel-plugin-transform-remove-console 配置在.umirx.ts/js中 export default…...

(生物信息学)R语言绘图初-中-高级——3-10分文章必备——饼图(初级)

生物信息学文章的发表要求除了思路和热点以外,图片绘制是否精美也是十分重要的,本专栏为(生物信息学)R语言绘图初-中-高级——3-10分文章必备,主要通过大量文献,总结3-10分文章中高频出现的各种图片,并给大家提供图片复现的R语言代码,及图片识读。 本专栏将向大家介绍…...

AI ppt生成器 Tome

介绍 一款 AI 驱动的 PPT/幻灯片内容辅助生成工具。只需要输入一个标题或者一段特定的描述&#xff0c;AI 便会自动生成一套包括标题、大纲、内容、配图的完整 PPT。 Tome平台只需要用户输入一句话&#xff0c;就可以自动生成完整的PPT&#xff0c;包括文字和图片。功能非常强…...

Linux与Windows下追踪网络路由:traceroute、tracepath与tracert命令详解

简介 在进行网络诊断或排查问题时&#xff0c;了解数据包从源主机到目标主机之间的具体传输路径至关重要。Linux系统提供了traceroute和tracepath工具来实时显示链路路径信息&#xff0c;而Windows则使用了tracert命令实现相同的功能。本文将详细介绍这三个命令的用法及其在不…...

图解JVM (及一些垃圾回收\GC相关面试题 持续更新)

垃圾回收&#xff0c;顾名思义就是释放垃圾占用的空间&#xff0c;从而提升程序性能&#xff0c;防止内存泄露。当一个对象不再被需要时&#xff0c;该对象就需要被回收并释放空间。 Java 内存运行时数据区域包括程序计数器、虚拟机栈、本地方法栈、堆等区域。其中&#xff0c;…...

linux 系统安全及应用

一、账号安全基本措施 1.系统账号清理 1.将用户设置为无法登录 /sbin/nologin shell——/sbin/nologin却比较特殊&#xff0c;所谓“无法登陆”指的仅是这个用户无法使用bash或其他shell来登陆系统而已&#xff0c;并不是说这个账号就无法使用系统资源。举例来说&#xff0c;…...

如何查看崩溃日志

​ 目录 描述 思路 查看ipa包崩溃日志 简单查看手机崩溃信息几种方式 方式1:手机设置查看崩溃日志 方式2: Xocde工具 方式3: 第三方软件克魔助手 环境配置 实时日志 奔溃日志分析 方式四&#xff1a;控制台资源库 线上崩溃日志 线上监听crash的几种方式 方式1: 三…...

使用HttpSession和过滤器实现一个简单的用户登录认证的功能

这篇文章分享一下怎么通过session结合过滤器来实现控制登录访问的功能&#xff0c;涉及的代码非常简单&#xff0c;通过session保存用户登录的信息&#xff0c;如果没有用户登录的话&#xff0c;会在过滤器中处理&#xff0c;重定向回登录页面。 创建一个springboot项目&#…...

SEO全自动发布外链工具源码系统:自动增加权重 附带完整的搭建安装教程

SEO全自动发布外链工具是一款基于PHP和MySQL开发的外链发布工具。它通过自动化流程&#xff0c;帮助站长快速、有效地发布外链&#xff0c;提高网站的权重和排名。该工具支持多种外链发布平台&#xff0c;如论坛、博客、分类信息等&#xff0c;可自定义发布内容和格式&#xff…...

Qt隐式共享浅析

一、什么是隐式共享 Qt 的隐式共享&#xff08;implicit sharing&#xff09;机制是一种设计模式&#xff0c;用于在进行数据拷贝时提高效率和减少内存占用。 在 Qt 中&#xff0c;许多类&#xff08;如 QString、QList 等&#xff09;都使用了隐式共享机制。这意味着当这些类…...

2023年我国网络安全法律法规一览

2023 年&#xff0c;是我国网络安全和数据安全领域法制建设持续发展的一年。政府进一步加大网络安全法规的制定和实施力度&#xff0c;不断强化数据安全和关键信息基础设施的保护&#xff0c;中央政府、国务院、中央网信办、工信部及各地方政府部门在《关键信息基础设施安全保护…...

Qt/QML编程学习之心得:一个音频播放器的实现(29)

在window下&#xff0c;打开音乐播放器&#xff0c;然后打开一个.mp3文件&#xff0c;就可以实现播放了&#xff0c;那么在Qt/QML中如何实现呢&#xff1f;首先所有的设计都是基于音乐播放器的&#xff0c;嵌入式linux下同样也有音乐播放器&#xff0c;比如mplayer。其调用方法…...

【数据结构】数据结构中应用题大全(完结)

自己在学习过程中总结了DS中几乎所有的应用题&#xff0c;可以用于速通期末考/考研/各种考试。很多方法来源于B站大佬&#xff0c;底层原理本文不做过多介绍&#xff0c;建议自己研究。例题大部分选自紫皮严书。pdf版在主页资源 一、递归时间/空间分析 1.时间复杂度的分析 设…...

WPF常用控件-Window

常用属性 这里重点记录一些关键且容易忘记的属性&#xff0c;那些很常用的如Title啥的就不在这里一一说明了。 任务栏按钮 ShowInTaskbar&#xff1a;是否在任务栏中显示应用按钮&#xff0c;默认为True。 层级 Topmost&#xff1a;应用是否始终在所有应用的最上层&#x…...

计算机网络——实验七

使用socket实现一个基于C/S架构的通信程序 &#xff08;1&#xff09;客户端发送给服务器请求&#xff0c;发送表征身份的用户名和密码("admin","123456")&#xff1b; &#xff08;2&#xff09;服务器根据客户端发来的信息验证身份&#xff0c;如果验证…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

初探用uniapp写微信小程序遇到的问题及解决(vue3+ts)

零、关于开发思路 (一)拿到工作任务,先理清楚需求 1.逻辑部分 不放过原型里说的每一句话,有疑惑的部分该问产品/测试/之前的开发就问 2.页面部分(含国际化) 整体看过需要开发页面的原型后,分类一下哪些组件/样式可以复用,直接提取出来使用 (时间充分的前提下,不…...

理想汽车5月交付40856辆,同比增长16.7%

6月1日&#xff0c;理想汽车官方宣布&#xff0c;5月交付新车40856辆&#xff0c;同比增长16.7%。截至2025年5月31日&#xff0c;理想汽车历史累计交付量为1301531辆。 官方表示&#xff0c;理想L系列智能焕新版在5月正式发布&#xff0c;全系产品力有显著的提升&#xff0c;每…...

Shell 解释器​​ bash 和 dash 区别

bash 和 dash 都是 Unix/Linux 系统中的 ​​Shell 解释器​​&#xff0c;但它们在功能、语法和性能上有显著区别。以下是它们的详细对比&#xff1a; ​​1. 基本区别​​ ​​特性​​​​bash (Bourne-Again SHell)​​​​dash (Debian Almquist SHell)​​​​来源​​G…...

Oracle实用参考(13)——Oracle for Linux物理DG环境搭建(2)

13.2. Oracle for Linux物理DG环境搭建 Oracle 数据库的DataGuard技术方案,业界也称为DG,其在数据库高可用、容灾及负载分离等方面,都有着非常广泛的应用,对此,前面相关章节已做过较为详尽的讲解,此处不再赘述。 需要说明的是, DG方案又分为物理DG和逻辑DG,两者的搭建…...

Excel 怎么让透视表以正常Excel表格形式显示

目录 1、创建数据透视表 2、设计 》报表布局 》以表格形式显示 3、设计 》分类汇总 》不显示分类汇总 1、创建数据透视表 2、设计 》报表布局 》以表格形式显示 3、设计 》分类汇总 》不显示分类汇总...

【中间件】Web服务、消息队列、缓存与微服务治理:Nginx、Kafka、Redis、Nacos 详解

Nginx 是什么&#xff1a;高性能的HTTP和反向代理Web服务器。怎么用&#xff1a;通过配置文件定义代理规则、负载均衡、静态资源服务等。为什么用&#xff1a;提升Web服务性能、高并发处理、负载均衡和反向代理。优缺点&#xff1a;轻量高效&#xff0c;但动态处理能力较弱&am…...

Ubuntu 可执行程序自启动方法

使用 autostart&#xff08;适用于桌面环境&#xff09; 适用于 GNOME/KDE 桌面环境&#xff08;如 Ubuntu 图形界面&#xff09; 1. 创建 .desktop 文件 sudo vi ~/.config/autostart/my_laser.desktop[Desktop Entry] TypeApplication NameMy Laser Program Execbash -c &…...

【Docker 02】Docker 安装

&#x1f308; 一、各版本的平台支持情况 ⭐ 1. Server 版本 Server 版本的 Docker 就只有个命令行&#xff0c;没有界面。 Platformx86_64 / amd64arm64 / aarch64arm(32 - bit)s390xCentOs√√Debian√√√Fedora√√Raspbian√RHEL√SLES√Ubuntu√√√√Binaries√√√ …...