zoukankan      html  css  js  c++  java
  • 整数中1出现的次数(从1到n整数中1出现的次数)

    时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 

    题目描述

    求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
     
    思路:
      最笨的方法,就是用两个循环,外部循环取数,内部循环取每位数上的值,判断是否为1,时间复杂度达到了O(n^2)级别
    class Solution {
    public:
        int NumberOf1Between1AndN_Solution(int n)
        {
            if(n < 0)
                return 0;
            int count = 0;
            for(int i =n;i>0;i-- )
            {
                for(int j =i;j > 0;j /=10)
                {
                    if(j %10 == 1)
                        count++;
                }
            }
            return count;
        }
    };

      另一种方法就是找出规律,归纳出合理的公式

      先固定某位数的值为1,将一个数分为两部分,高位和低位。假设一个五位数n,用m来分割高低位,根据设定的整数位置,对n分割,分为两部分,高位n/m,低位就是n%m,分为三种情况,(再假设m所在位数为百位)

      1、当百位数>=2,如n = 31456,m = 100,则高位a = 314,低位b = 56

        100  ~ 199

        1100~1199
        …
        31100~31199

        此时百位为1 的次数有a/10 + 1 = 32(最高两位0~31),每一次都包含了100~199这100个连续的点,所以共有(a / 10 + 1) * 100个点的百位为1

      2、当百位数 ==1,如n = 31156,m = 100,则a = 311,b = 56  

        100  ~ 199

        1100~1199
        …
        31100~31156

        此时百位为1,共有a/10(最高两位0~30)次包含100个连续的点,即(a / 10) * 100 ,再加上局部点00~56,共有b+1次,即总共1的次数为(a/10)* 100 + b+1次

      3、当百位数 ==0时,如n=31056,m = 100,则a = 310,b = 56

        100  ~ 199

        1100~1199
        …
        31000~31056

        一共有(a/10) *100个1

      综上三种情况,当百位对于0或者>=2时,有(a+8)/10次包含有100个连续点,还有当百位==1(a%10 ==1)时,需要增加局部点b+1

      (之所以加8,是因为当百位数为0,则a / 10 = (a + 8)/10,当百位>=2,加8会产生进位,效果等同于(a/10 + 1),这样就可以将上述三种情况用一个表达式进行表达:

          count = (a + 8) // 10 * m + (a % 10 == 1) * (b + 1)

    class Solution {
    public:
        int NumberOf1Between1AndN_Solution(int n)
        {
            if(n < 0)
                return 0;
            int i = 1;
            int count = 0;
            for(i = 1;i <= n;i*=10)
            {
                int a = n/i,b = n%i;
                count += (a+8)/10*i + (a % 10 == 1)*(b+1);
            }
            return count;
        }
    };
  • 相关阅读:
    美国和日本不是盟友吗,为什么拒绝出售F-22战斗机给日本?
    刚刚大学毕业,是选择创业还是选择公司上班?
    现今的社会一定要结婚吗?
    事必躬亲果真是无能的表现?
    课外辅导机构,就让疫情灭了吧!
    这些年,我读书越来越少了!
    Python操作日志、加密、发送邮件、线程、生产者消费者
    Python模块操作之re、MySQL、Excel
    Python面向对象、迭代器、range和切片的区分
    Python模块、文件读写、异常
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12587094.html
Copyright © 2011-2022 走看看