欢迎来到王正伟的博客

返回顶部

面试题41:1~n整数中1出现的次数(C++)

题目地址:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/

题目描述

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

题目示例

示例 1:

输入:n = 12
输出:5

示例 2:

输入:n = 13
输出:6

解题思路

思路1:逐位来看,统计1在每个数位上出现的次数,每10个数,个位上的1就会出现一次,每100个数,十位的1就会出现一次。我们将n按照每个数位i划分成两部分,即left和right,然后拿到该数位i上的数与1进行判断,情况有三种,分别是left%10大于1、小于1、等于1,当该数位i上的数大于1时,1出现的次数为cnt+=(left/10+1)*i,当该数位上的数等于1时,1出现的次数为cnt+=left/10*i+right+1,当该数位上的数字小于1时,1出现的次数为cnt+=left/10*i。通过分析,我们将这三种情况合为一种情况,即1出现的次数为cnt+=(left+8)/10*i+(left%10==1)*(right+1)。

思路2:计算该数的中低高位,然后对中位是否为1的情况进行判断。

程序源码

思路1

class Solution {
public:
    int countDigitOne(int n) {
        if(n == 0) return 0;
        long cnt = 0;
        for(long i = 1; i <= n; i *= 10)
        {
            long left = n / i;
            long right = n % i;
            cnt += (left+8)/10*i + (left%10==1)*(right+1);
        }
        return cnt;
    }
};

思路2

class Solution {
public:
    int countDigitOne(int n) {
        if(n == 0) return 0;
        long cnt = 0;
        for(long i = 1; i <= n; i *= 10)
        {
            long high = n / (i * 10); //计算高位,比如求三位数123,则百位high = n / 100 = 1
            long mid = (n / i) % 10; //计算中位,比如求三位数,则十位mid= n / 10 %10 = 2
            long low = n % i; //计算低位,比如求三位数,则个位low = n % 10 = 3
            if(mid == 0) cnt += (high) * i;
            if(mid == 1) cnt += high * i + low + 1;
            if(mid > 1) cnt += (high + 1) * i;
        }
        return cnt;
    }
};

参考文章

https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/mian-shi-ti-43-1nzheng-shu-zhong-1chu-xian-de-ci-3/

https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/zhao-gui-lu-de-ti-mu-by-sysuzyc/

https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/c-shuang-bai-ji-lu-yi-xia-si-lu-by-ian1995/

posted @ 2020-04-26 10:16  Mr.King~  阅读(616)  评论(0编辑  收藏  举报