剑指offer43题

**

剑指offer43题 1-N整数中1出现的次数

**

题解:
总体思想就是分类,先求所有数中个位是 1 的个数,再求十位是 1 的个数,再求百位是 1 的个数…

假设 n = xyzdabc,此时我们求千位是 1 的个数,也就是 d 所在的位置。

那么此时有三种情况,

d == 0,那么千位上 1 的个数就是 xyz * 1000
d == 1,那么千位上 1 的个数就是 xyz * 1000 + abc + 1
d > 1,那么千位上 1 的个数就是 xyz * 1000 + 1000
为什么呢?

当我们考虑千位是 1 的时候,我们将千位定为 1,也就是 xyz1abc。

对于 xyz 的话,可以取 0,1,2…(xyz-1),也就是 xyz 种可能。

当 xyz 固定为上边其中的一个数的时候,abc 可以取 0,1,2…999,也就是 1000 种可能。

这样的话,总共就是 xyz*1000 种可能。

注意到,我们前三位只取到了 xyz-1,那么如果取 xyz 呢?

此时就出现了上边的三种情况,取决于 d 的值。

d == 1 的时候,千位刚好是 1,此时 abc 可以取的值就是 0 到 abc ,所以多加了 abc + 1。

d > 1 的时候,d 如果取 1,那么 abc 就可以取 0 到 999,此时就多加了 1000。

示例:

如果n = 4560234
让我们统计一下千位有多少个 1
xyz 可以取 0455, abc 可以取 0999
4551000 to 4551999 (1000)
4541000 to 4541999 (1000)
4531000 to 4531999 (1000)
...
  21000 to   21999 (1000)
  11000 to   11999 (1000)    
   1000 to    1999 (1000)
总共就是 456 * 1000

如果 n = 4561234
xyz 可以取 0455, abc 可以取 0999
4551000 to 4551999 (1000)
4541000 to 4541999 (1000)
4531000 to 4531999 (1000)
...
1000 to 1999 (1000)
xyz 还可以取 456, abc 可以取 0234
4561000 to 4561234 (234 + 1)
总共就是 456 * 1000 + 234 + 1

如果 n = 4563234
xyz 可以取 0455, abc 可以取 0999    
4551000 to 4551999 (1000)
4541000 to 4541999 (1000)
4531000 to 4531999 (1000)
...
1000 to 1999 (1000)
xyz 还可以取 456, abc 可以取 0999
4561000 to 4561999 (1000)
总共就是 456 * 1000 + 1000


代码

public class offer43 {
	//记录1的个数
	int cnt=0;
	public int NumberOf1Between1AndN_Solution(int n) {
		//按个位、十位、百位上1得个数相加之和
		for (int i = 1; i <=n;i*=10) {
			//求取对应位的商
			int m=n/i;
			//对应位的余数
			int a=n%i;
			//将三种情况合并
			//如果对应位<=1,+8不会影响/10后结果,
			//如果>1,加8后原来/10后结果基础上+1,满足了对应位大于1的情况
			cnt+=(m+8)/10*i +(m%10==1 ? a+1:0);
		}
		return cnt;
	    
    }

}

再看一个具体的例子。
链接:https://leetcode-cn.com/problems/number-of-digit-one/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-50/
来源:力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值