LeetCode-233.Number of Digit One

https://leetcode.com/problems/number-of-digit-one/

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.

Hint:

  1. Beware of overflow.

如果不用暴力求解,显然需要找寻规律

方法一

拿n=21345作为例子分析:

可以将n分为三部分:0-(0)1345,1346-11345和11346-21345

第一部分0-(0)1345可以递归求解21345-20000得结果

第二、三部分分别求(设n最高位是n0

小于n中当最高位为1得,一共出现10000-19999共10000次,这是因为n0=2,如果n0=1(如11345),则出现11345-10000+1次

剩下分析除n0外其它四位情况,后四位可以任选一位是1,其余可以在0-9选择。因此是4*1000次,因为是两部分,所以*2

更详细分析参考《剑指Offer》P175

int countDigitOne(int n) 
    {
        if (n < 1)
    		return 0;
    	int n0, len,res = 0,num;//n0记录最高位,len记录位数
    	while (n>0)
    	{
    		if (n < 10)
    		{
    			res++;
    			break;
    		}	
    		n0 = n;
    		len = 0;
    		while (n0 / 10 > 0)
    		{
    			n0 /= 10;
    			len++;
    		}
    		num = pow(10, len);
    		if (n0 == 1)//计算最高位出现1个个数
    			res += n - num + 1;
    		else
    			res += num;
    		res += n0*len*(num / 10);//括号是防止溢出
    		n -= n0*num;
    	}
    	return res;
    }

方法二、

分别讨论每一位为1的情况

参考 https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python

int countDigitOne(int n) 
    {
        int res = 0, a, b;
    	for (long m = 1; m <= n; m *= 10)
    	{
    		a = n / m;
    		b = n % m;
    		res+= (a + 8) / 10 * m + (a % 10 == 1) * (b + 1);
    	}
    	return res;
    }

例:

 以百位上1为例子: 假设百位上是0, 1, 和 >=2 三种情况: 

case 1: n=3141092, a= 31410, b=92. 计算百位上1的个数应该为 3141 *100 次

case 2: n=3141192, a= 31411, b=92. 计算百位上1的个数应该为 3141 *100 + (92+1) 次

case 3: n=3141592, a= 31415, b=92. 计算百位上1的个数应该为 (3141+1) *100 次

 以上三种情况可以用 一个公式概括: (a + 8) / 10 * m + (a % 10 == 1) * (b + 1);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值