1~n整数中1出现的次数(剑指offer43 力扣233)Java

简介: 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

一、题目描述



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

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


示例 1:

输入:n = 12

输出:5


示例 2:

输入:n = 13

输出:6

 

限制:

1 <= n < 2^31


二、思路讲解


     

本题采用的思路为,按位逐一找到每一位上1出现的个数,然后加起来即可,关于每一位1的个数,有三种情况:


1、当前位上为0


以n=2705为例,假设我们要找十位上1出现的次数,那么当前位上是0,高位上是27,低位上是5;那么要找十位为1的数字范围是 0010~2619,就相当于固定了十位为1,然后任意修改其他位的数字,可能的情况为000~269,共有270中情况,270其实等于 高位 * 位权值  ,即27*10+1;


2、当前位上为1


以n=2715为例,假设我们要找十位上1出现的次数,那么要找的数字是 0010~2715,就相当于固定了十位为1,然后任意修改其他位的数字,可能的情况为000~275,共有276中情况,276其实等于 高位* 位权值 + 低位 + 1 ,即26*10+9+1;


3、当前位上为2~9


以n=2755为例,假设我们要找十位上1出现的次数,那么要找的数字是 0010~2719,就相当于固定了十位为1,然后任意修改其他位的数字,可能的情况为000~279,共有280中情况,280其实等于 (高位+1)* 位权值 ,即(27+1)*10;


然后逐位计算1的次数之后,相加即可。


三、Java代码实现

class Solution {
    public int countDigitOne(int n) {
        int digit = 1;  //位因子,个位为1,十位为10,百位为100……
        int res = 0;    //总次数     
        int high = n / 10, cur = n % 10, low = 0;
        while(high != 0 || cur != 0) {
            if(cur == 0){   //如果当前位上为0
                res += high * digit;
            } 
            else if(cur == 1){  //如果当前位上为1
                res += high * digit + low + 1;
            } 
            else {  //如果当前位为 2~9
                res += (high + 1) * digit;
            }
            //更新高位、当前位、低位
            low += cur * digit;
            cur = high % 10;
            high = high / 10;
            digit = digit * 10;
        }
        return res;
    }
}


四、时空复杂度分析


       

时间复杂度 O(log n): 循环内的计算操作使用 O(1) 时间;循环次数为数字 n 的位数,即 log10_n,因此循环使用 O(log n)时间。


空间复杂度 O(1): 几个变量使用常数大小的额外空间。

相关文章
|
1月前
|
存储
LeetCode整数反转
解决LeetCode上的整数反转问题的几种方法,包括错误的方法和优化后的解决方案,以及如何避免反转后的整数超出32位有符号整数范围的问题。
34 1
|
1月前
【LeetCode】整数翻转
【LeetCode】整数翻转
14 1
|
2月前
|
Java
java基础(10)数据类型中的整数类型
Java中的整数类型包括byte、short、int和long。整数字面值默认为int类型,加L表示long类型。整数字面值可以是十进制、八进制(0开头)或十六进制(0x开头)。小容量类型(如int)可自动转换为大容量类型(如long),但大容量转小容量需强制转换,可能导致精度损失。
42 2
|
1月前
|
存储 C++
Leetcode第十二题(整数转罗马数字)
LeetCode第12题“整数转罗马数字”的解题方法,包括罗马数字的基本规则和特殊规则,以及如何使用C++实现整数到罗马数字的转换。
15 0
|
1月前
|
C++
Leetcode第十三题(罗马数字转整数)
这篇文章介绍了LeetCode第13题“罗马数字转整数”的解题方法,通过一个C++的类`Solution`中的`romanToInt`函数来实现,该函数使用哈希表和遍历字符串的方法,根据罗马数字的规则将输入的罗马数字字符串转换为对应的整数值。
47 0
|
1月前
|
算法 C++
Leetcode第八题(字符串转换整数(atoi))
这篇文章介绍了LeetCode上第8题“字符串转换整数(atoi)”的解题思路和C++的实现方法,包括处理前导空格、正负号、连续数字字符以及整数溢出的情况。
17 0
|
1月前
|
算法 Java
LeetCode(一)Java
LeetCode(一)Java
|
3月前
|
算法
LeetCode第12题目整数转罗马数字
该文章介绍了 LeetCode 第 12 题整数转罗马数字的解法,通过使用 TreeMap 按照整数从大到小排序,先使用大的罗马数字表示整数,再用小的,核心是先表示完大的罗马数字,想通此点该题较简单。
LeetCode第12题目整数转罗马数字
|
3月前
|
算法
LeetCode第8题字符串转换整数 (atoi)
该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
LeetCode第8题字符串转换整数 (atoi)
|
3月前
|
算法
LeetCode第13题目罗马数字转整数
该文章介绍了 LeetCode 第 13 题罗马数字转整数的解法,通过从大到小解析罗马数字,根据罗马数字的特点,按照从大到小的顺序匹配罗马数字和整数的关系,从而解决该问题,同时强调要注意观察题目考查的知识点特征。