• 整数中 1 出现的次数(从 1 到 n 整数中 1 出现的次数)



    求出 1 ~ 13 的整数中 1 出现的次数,并算出 100 ~ 1300 的整数中 1 出现的次数?可以发现 1 ~ 13 中包含 1 的数字有 1、10、11、12、13,因此共出现 6 次。现需要把问题更加普遍化,可以很快的求出任意非负整数区间中 1 出现的次数(从 1 到 n 中 1 出现的次数)


    解题思路

    设定整数点(1、10、100、1000、10000)分别对应 n 的个位、十位、百位、千位、万位,我们要做的就是:考虑每一位出现 1 的情况,算出各自符合题意的数的数量,并进行相加,就能得出想要的结果。

    现以整数点 100 为例,使用 100 对 n 进行分割,高位为 n/100,低位为 n%100

    考虑三种情况:

    • 以 31456 为例,百位对应的数 4 >= 2,此时高位 a = 314,低位 b = 56,因为 4 >= 2,所以肯定会有百位为 1 的情况,此时无论其他位的数是多少,都将满足题意。高位可以取 32 种情况(0 ~ 31),低位则总是 100 个连续的点,因此共有 (a/10 + 1)*100 个数
    • 以 31156 为例,百位对应的数 1 == 1,此时高位 a = 311,低位 b = 56,因为百位已经是 1,此时无论其他位的数是多少,都将满足题意。高位的取值要分情况,当最高两位范围是 0 ~ 30 时,和上一条一样;当 a = 311(取 31) 时,则对应的低位只有 0 ~ 56,共 b + 1 次,因此总共有 (a/10)*100 + (b + 1)
    • 以 31056 为例,百位对应的数为 0,此时高位 a = 310,低位 b = 56,百位为 0,所以高位的前两位只能去 0 ~ 30,这样百位才能取 1,因此总共有 (a/10)*100

    综合以上三种情况,我们可以得出:

    • 当百位 == 0 或 >= 2 时,有 (a+8)/10 次包含所有 100 个点(之所以补 8,是因为当百位为 0,则 a/10 == (a+8)/10,当百位 >= 2,补 8 会产生进位位,效果等同于 (a/10+1))
    • 当百位 == 1,即 (a%10==1),则需要增加局部点 b+1
    public class Solution {
        public int NumberOf1Between1AndN_Solution(int n) {
            int count = 0;
            long split = 1;
            for(int i = 1; i <= n; i *= 10) {
                int a = n/i, b = n%i;
                count = count + ((a+8)/10)*i + ((a%10 == 1) ? (b + 1) : 0);
            }
            return count;
        }
    }
    

  • 相关阅读:
    Encrypted Handshake Message
    RSAParameters Struct
    What if JWT is stolen?
    What's the difference between JWTs and Bearer Token?
    RSA Algorithm Example
    第18届Jolt大奖结果公布
    Ruby on rails开发从头来(windows)(三十六) 调试技巧
    Ruby on rails开发从头来(四十二) ActiveRecord基础(主键和ID)
    YouTube开放基础技术架构 让用户建自家YouTube
    Ruby on rails开发从头来(四十) ActiveRecord基础(Boolean属性)
  • 原文地址:https://www.cnblogs.com/Yee-Q/p/13828625.html
Copyright © 2020-2023  润新知