剑指offer:整数中1出现的次数(从1到n整数中1出现的次数)

Problem Link:https://www.nowcoder.com/practice/bd7f978302044eee894445e244c7eee6?tpId=13&tqId=11184&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

 

题目描述

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

 

思路:算法思想是这样的,求1~n整数中1出现的次数。假设n=21345,那么可以先划分为1~1345和1346~21345这两个区间。对于1346~21345这个区间,分成1346~11345和11346~21345这两段。然后先求出1346~21345范围内第一位不为1且后四位数中至少一位为1的总个数。根据排列组合,得2*4*10^3=8000。那么这里8000就是1346~21345范围内第一位不为1且后四位数中至少一位为1的总个数。再求出最高位(万位)为1的数目,相加就是1346~21345范围内的总数目。然后再采用相同方法,对1~1345进行递归求解。

 

AC code:

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n==0)
        {
            return 0;
        }
        else if(n<10)
        {
            return 1;
        }
        int ans=0;
        int wei=log10(n)+1;
        int first = n/PowerBase10(wei-1);//最高位
        int nextN=n%PowerBase10(wei-1);//余数
        int numFirst;
        int numOther;
        if(first==1)
        {
            numFirst = nextN + 1;
        }
        else
        {
            numFirst= PowerBase10(wei-1);
        }
        numOther = first * (wei-1) * PowerBase10(wei-2);
        ans += numFirst + numOther + NumberOf1Between1AndN_Solution(nextN);
        return ans;
    }
    
    int PowerBase10(int n)
    {
        int res=1;
        for(int i=1;i<=n;i++)
        {
            res*=10;
        }
        return res;
    }
};

 

 

 

 

你可能感兴趣的:(ACM)