面试题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; } };
参考文章
-----------------------------------
心之所向,素履所往;生如逆旅,一苇以航。
------------------------------------------