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

    题目

    输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。

    思路

      1.先根据数组的最高位计算1出现的次数 

    • 如果只有一位数且该为是0,返回0 
    • 如果只有一位数且该为大于0,则1出现的次数只有1次
    • 如果最高位数字大于1,则最高位1出现的次数是10^len-1次方 
    • 如果最高位数字不大于1,1出现的次数是除最高位所有的数字+1次 

      2.其他位1出现的次数:最高位不变,固定其他一位,剩余的位数全排列 

      3.去除最高位,递归求得依次剩余的位数 

    #include <iostream>
    #include <sstream>
    #include <cmath>
    using namespace std;
    
    class Solution
    {
        public:
            int num_of_one(string s);
            int digit(const unsigned int n);
    };
    int Solution::num_of_one(string s)
    {
        if(s.empty()||s.size()<=0||*s.begin()<='0'||*(--s.end())>'9')
            return 0;
        
        //1.先根据数组的最高位计算1出现的次数 
        int first=*s.begin()-'0';
        unsigned int len=s.size();
        if(len==1&&first==0) //如果只有一位数且该为是0,返回0 
            return 0;
        else if(len==1&&first>0)//如果只有一位数且该为大于0,则1出现的次数只有1次 
            return 1;
        
        int num_first_digit=0;
        if(first>1)//如果最高位数字大于1,则最高位1出现的次数是10^len-1次方 
            num_first_digit=digit(len-1);
        else if(first==1)//如果最高位数字不大于1,1出现的次数是除最高位所有的数字+1次 
            num_first_digit=*(++s.begin())-'0'+1;
        
        //2.其他位1出现的次数:最高位不变,固定其他一位,剩余的位数全排列 
        int num_other_digit=first*(len-1)*digit(len-2);
        s.erase(s.begin());
        //3.去除最高位,递归求得依次剩余的位数 
        int num_recursive=num_of_one(s);
        
        return num_first_digit+num_other_digit+num_recursive;
    }
    int Solution::digit(const unsigned int n)
    {
        return (int)pow(10,n);
    } 
    int main()
    {
        long n;
        cin>>n;
        
        stringstream ss;
        ss<<n; 
        Solution s;
        cout<<s.num_of_one(ss.str())<<endl;
        return 0;
    }

     二

      对于个位数,N中1出现的次数不仅和N的个位数有关,还和N的十位数有关

        1.如果个位数大于1,则个位数1出现的次数=十位数字+1;

        2.如果个位数字为0,则个位数1出现的次数=十位数字;

      对于十位数字,1出现的次数不仅和十位数有关,还和个位数有关

        1.如果十位数字=1,则十位1出现的次数=个位数字+1;

        2.如果十位数字>1,则十位1出现的次数=10;

      对于百位数字,设定整数点(如1、10、100等等)作为位置点i(对应n的各位、十位、百位等等),分别对每个数位上有多少包含1的点进行分析。

    1. 根据设定的整数位置,对n进行分割,分为两部分,高位n/i,低位n%i
    2. 当i表示百位,且百位对应的数>=2,如n=31456,i=100,则a=314,b=56,此时百位为1的次数有a/10+1=32(最高两位0~31),每一次都包含100个连续的点,即共有(a/10+1)*100个点的百位为1
    3. 当i表示百位,且百位对应的数为1,如n=31156,i=100,则a=311,b=56,此时百位对应的就是1,则共有a/10(最高两位0-30)次是包含100个连续点,当最高两位为31(即a=311),本次只对应局部点00~56,共b+1次,所有点加起来共有(a/10*100)+(b+1),这些点百位对应为1
    4. 当i表示百位,且百位对应的数为0,如n=31056,i=100,则a=310,b=56,此时百位为1的次数有a/10=31(最高两位0~30),所以加起来公(a/10)*100个点

    所以,当百位对应0或>=2时,有(a+8)/10次包含所有100个点,还有当百位为1(a%10==1),需要增加局部点b+1

    class Solution {
    public:
        int NumberOf1Between1AndN_Solution(int n)
        {
            if(n<1)
                return 0;
            
            int base=1;
            int sum=0;
            while(n/base)
            {
                int lowNum=n-(n/base)*base;
                int curNum=n/base%10;
                int heightNum=n/(base*10);
                
                if(curNum==0)
                    sum+=heightNum*base;
                else if(curNum==1)
                    sum+=heightNum*base+lowNum+1;
                else
                    sum+=(heightNum+1)*base;
                
                base*=10;
            }
            return sum;
        }
    };
  • 相关阅读:
    20145202、20145225、20145234 《信息安全系统设计基础》实验二 固件设计
    20145225 《信息安全系统设计基础》第12周学习总结
    GDB调试汇编堆栈过程分析
    20145118 《Java程序设计》课程总结
    JAVA第十周《网络编程》学习内容总结
    JAVA课程实验报告 实验五 JAVA网络编程及安全
    20145118《Java程序设计》 第9周学习总结
    20145118 《Java程序设计》 实验报告四
    20145118《Java程序设计》 第8周学习总结
    20145118 《Java程序设计》 实验报告三
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10241808.html
Copyright © 2011-2022 走看看