跟着姚桑学算法-从1到n整数中1出现的次数

简介: 剑指offer算法

题. 从1到n整数中1出现的次数

输入一个整数 n,求从 1 到 n 这 n 个整数的十进制表示中 1 出现的次数。

例如输入 12,从 1 到 12 这些整数中包含 “1” 的数字有 1,10,11 和 12,其中 “1” 一共出现了 5 次。

数据范围
1≤n≤10^9

样例

输入: 12
输出: 5

【题解】-- 按位数

一个数字: abcdef
求解 1 出现的次数即为各个位为1时其次数总和。(分别讨论各个位为 1 时,这个数字的变化范围,也就得到了总个数)

  • 讨论 f 位,则其高位的范围可以为 0 ~ abcde-1,低位只能为 1

f = 0 时,1, 11, 21, …, abcd(e-1)1。共计 abcde 个 1
f = 1 时,abcde1 也符合,共计 abcde + 1
f > 1 时,其高位范围可以为 0 ~ abcde

  • 讨论 e 位,则其高位范围可以为 0 ~ abcd-1, 低位可以为 0 ~ 9

e = 0, 10, 110, 210, …, abc(d-1)10。共计 abcd 个 0 ~ 9
e = 1, abcd1f 也符合,共计 abcd 个 0 ~ 9 + 1 个 0 ~ f
e > 1, 则其高位可以为 0 ~ abcd
… 以此类推

复杂度分析:

一个n位数一共有ln(n) / ln(10)位, 所以复杂度是 O(logn)级。

C++代码实现:

class Solution {
public:
    int numberOf1Between1AndN_Solution(int n) {

        int res = 0;
        for (int m = 1; m <= n; m *= 10) {
            int left = n / (10 * m);
            int right = n % m;
            res += left * m;
            if ((n / m) % 10 == 1) res += right + 1;
            if ((n / m) % 10 > 1) res += m;
            //cout << left << " " << right << " " << res << endl;
        } 
        return res;
    }
};
目录
相关文章
|
2月前
|
自然语言处理 Rust 算法
【算法】13. 罗马数字转整数(多语言实现)
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 | 字符 | 数值 | |--|--| | I | 1 | | V | 5 | | X | 10 | | L | 50 | | C | 100 | | D | 500 | | M | 1000 | 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1
【算法】13. 罗马数字转整数(多语言实现)
|
2月前
|
算法 测试技术 C#
【数位dp】【C++算法】600. 不含连续1的非负整数
【数位dp】【C++算法】600. 不含连续1的非负整数
|
2月前
|
算法 Java C++
试题 算法训练 整数拆分
试题 算法训练 整数拆分
32 0
|
2月前
|
算法 Java
[Java·算法·简单] LeetCode 13. 罗马数字转整数 详细解读
[Java·算法·简单] LeetCode 13. 罗马数字转整数 详细解读
33 0
|
1月前
|
SQL 算法 数据挖掘
深入探索力扣第12题:整数转罗马数字的算法之旅
深入探索力扣第12题:整数转罗马数字的算法之旅
|
2月前
|
算法 C语言
【C语言】求最小新整数(贪心算法)
【C语言】求最小新整数(贪心算法)
25 1
|
2月前
|
算法
简记二分算法模板与代码案例:整数二分和浮点数二分
本文介绍了两种算法模板,分别是整数二分和浮点数二分。
20 0
|
2月前
|
算法 测试技术 C++
【数论】【分类讨论】【C++算法】1611使整数变为 0 的最少操作次数
【数论】【分类讨论】【C++算法】1611使整数变为 0 的最少操作次数
|
2月前
|
算法 测试技术 C++
【数位dp】【C++算法】600. 不含连续1的非负整数
【数位dp】【C++算法】600. 不含连续1的非负整数
|
2月前
|
算法
算法题 — 整数转二进制,查找其中1的数量
算法题 — 整数转二进制,查找其中1的数量
20 0