数据结构&算法&人工智能

剑指offer编程题—整数中1出现的次数

2020-04-07  本文已影响0人  零岁的我

题目描述
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

解题思路
思路1:
直接暴力循环,时间复杂度位O(nlogn)
思路2
主要是寻找数学规律,时间复杂度为O(logn),详情参考网友链接。
参考连接:整数中1出现的次数(从1到n整数中1出现的次数)

代码实现:

#include<iostream>
#include<cmath>
using namespace std;

//题解1:暴力循环
class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int count=0;
        int temp;
        for(int i=1;i<=n;++i){
            temp=i;
            while(temp){
                if(temp%10==1) ++count;
                temp/=10;
            }
        }
        return count;
    }
};

/*题解2:找规律:
1.如果第i位(自右向左,i从第1位开始标号)上的数字是0,则第i位可能出现1的次数由更高位决定,
  出现1的次数=更高位数*当前位数的权重(10^(i-1));
2.如果第i位上的数字是1,则第i位出现1的次数不仅受更高位影响,还受低位影响,
  出现1的次数=更高位数*当前位数的权重(10^(i-1))+1+低位数
3.如果第i位上数字大于1,则第i位出现1的次数由更高位决定,
  出现1的次数=(更高位数+1)*当前位数的权重(10^(i-1))
*/
class Solution1 {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int r = 0;
        for(long long i = 1; i <= n; i *= 10){
            //如果第i位上数字大于1,表达式( n / i + 8)实现了向更高位进1, ( n / i + 8)/ 10实现了(更高位+1)的操作
            //如果第i位上数字小于等于1,表达式( n / i + 8) / 10求得的就是更高位的数字。
            //表达式(n / i % 10 == 1) 用于判断第i位上是否为1
            //表达式(n / i % 10 == 1) * (n % i + 1)实现了(低位数+1)
            r += ( n / i + 8) / 10 * i + (n / i % 10 == 1) * (n % i + 1);
        }
        return r;
    }
};

int main(int argc,char **argv)
{
    int n=113;
    int res;
    Solution sol;
    res=sol.NumberOf1Between1AndN_Solution(n);
    cout<<res<<endl;

    Solution1 sol1;
    res=sol1.NumberOf1Between1AndN_Solution(n);
    cout<<res<<endl;
    return 0;
}


上一篇 下一篇

猜你喜欢

热点阅读