每日算法系列【LeetCode 233】数字 1 的个数

本文介绍了一种高效算法,用于计算小于等于给定整数的所有非负整数中数字1出现的总数。通过数学方法和数位动态规划两种途径解析问题,提供了C++和Python的实现代码。

题目描述

给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。

示例1

        输入:
13
输出:
6
解释:
数字 1 出现在以下数字中: 1, 10, 11, 12, 13 。
      

题解

这题是我搜数位 dp 题目搜出来的,于是我直接用数位 dp 方法把它过了,后来发现其实没必要这么麻烦,简单的计算就能算出来了,这里两个方法我都讲一下。

数学方法

我们不妨用 n = 12345 来举个例子。要求小于等于 n 的数字里有多少个 1 ,我们不妨转换个角度,看某一位数字是 1 的话,有多少数字小于 n 。

例如从右向左数第 i = 2 位(数字 3 ),如果这一位取 1 ,那么左边 2 位如果取 0~11 ,那么右边 2 位就没有任何限制,从 0 取到 99 都行。如果左边 2 位如果取 12 ,那么就得考虑 n 中第 i 位是几了,如果大于 1 ,那么右边 2 位还是没有限制;如果等于 1 ,那么右边 2 位只能取 0~45 ;如果等于 0 ,那就没得取了。

下面这张图是我打的草稿,看的更清楚一点:

v2-27800c7072d1f59f95a91c5cc5803f51_b.jpg

一般化描述就是,考虑从右往左数第 i 位是 1 的数字数量。那么 n 中第 i 位左边部分的数字是 \left\lfloor \frac{n}{10^{i+1}} \right\rfloor ,而右边可以取的数量是 10^i ,相乘就是总的数量 \left\lfloor \frac{n}{10^{i+1}} \right\rfloor \cdot 10^i 。如果左边直接取最大值,那么就要考虑第 i 位数字是几了,计算可以得到第 i 位数字为 \left\lfloor \frac{n}{10^{i}} \right\rfloor \% 10 ,记为 x 。如果 x > 1 ,那么右边无限制,有 10^i 种取法;如果 x = 1 ,那么右边有 n \% 10^i + 1 种取法;如果 x = 0 ,那么右边无法取,因为第 i 位都没法取 1 。

综上,令 x = \left\lfloor \frac{n}{10^{i}} \right\rfloor \% 10 ,那么答案就是:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法码上来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值