剑指offer 数组中1出现的次数

1.题目

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

来源:剑指offer
链接:https://www.nowcoder.com/practice/bd7f978302044eee894445e244c7eee6?tpId=13&tqId=11184&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

2.我的题解

笨方法,一个数一个数累加,一个数中一位一位累加。

class Solution {
    int numOf1(int n) {
        int res = 0;
        while (n) {
            if (n % 10 == 1)res++;
            n /= 10;
        }
        return res;
}
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
    	int res = 0;
        for (int i = 1; i <= n; i++) {
            res += numOf1(i);
        }
        return res;
    }
};

3.别人的题解

3.1 硬数版

我的代码太冗长了。
链接:https://www.nowcoder.com/questionTerminal/bd7f978302044eee894445e244c7eee6?answerType=1&f=discussion
来源:牛客网

public int NumberOf1Between1AndN_Solution(int n) {
    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;
}

3.2 数学归纳法公式版

链接:https://www.nowcoder.com/questionTerminal/bd7f978302044eee894445e244c7eee6?answerType=1&f=discussion
来源:牛客网
思路是分别计算个位、十位、百位…上出现 1的个数。
n =216为例:

  • 个位上: 1 ,11,21,31,.....211。个位上共出现(216/10)+ 11 。因为除法取整,210~216间个位上的1取不到,所以我们加8进位。
  • 你可能说为什么不加9,这里把最后取到的个位数为1的单独考虑。当前位上需要特殊考虑的取1的数量与当前位的数值、更低位的那些数有关。比如111112在计算个位数上为1的情况时,112+81了取12,111+8虽然没进1,但是由于有末位数为1的特殊情况,总数也加了1,因此+8的操作正好。
  • 十位上:10~19,110~119,210~216. 十位上可看成 求(216/10)=21个位上的1的个数然后乘10。这里再次把最后取到的十位数为1的单独拿出来,即210~216要单独考虑 ,个数为(216%10)+1
  • 后面以此类推。
  • 时间复杂度 :O(logn)
public int NumberOf1Between1AndN_Solution(int n) {
    int cnt = 0;
    for (int m = 1; m <= n; m *= 10) {
        int a = n / m, b = n % m;
        cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0);
    }
    return cnt;
}

4.总结与反思

发布了54 篇原创文章 · 获赞 0 · 访问量 1936

猜你喜欢

转载自blog.csdn.net/weixin_43951240/article/details/104148631
今日推荐