整数中1出现的次数

以 21345为例,统计1 ~ 21345中1出现的次数。

把21345分成两部分统计:1 ~ 1345 和 1346 ~ 21345

这样一来,如果统计出 1346 ~ 21345中1出现的次数。

1 ~ 1345中1出现的次数,可以看做是21345去掉最高位的子问题,因此可以递归处理。


下面就统计1346~ 21345中1出现的次数。

1. 首先统计最高位出现1的次数:

这里最高位为2,那么最高位为1时,只可能在10000 ~ 19999中,即1出现了10000次

如果最高位是1呢?即11345,那么最高位为1时,只可能在10000 ~ 11345中,即 1出现了1346次

		// 最高位出现1的次数
		if (first > 1) {
			numFirstDigit = (int) Math.pow(10, length - 1);
		} else {
			numFirstDigit = 1 + Integer.valueOf(str.substring(1));
		}

2. 统计其余位出现1的次数

把 11346 ~ 21345 分成两部分:  1346 ~ 11345 和 11346 ~ 21345,每一部分各10000个数。

如果是 11346 ~ 31346,则分成三部分:1346 ~ 11345 、11346 ~ 21345 和21346 ~ 31345,每一部分个10000个数。

即如果最高位是1,则分成1部分,如果最高位是2,则分成两部分,依次类推。


每一部分各10000个数,可以看成4位0~9的十位数的枚举,则1出现了4*1000次。

那么其余位出现1的总次数为:最高位*其余位数*Pow(10,其余位数-1)

		// 其余位 出现1的次数
		numOtherDigits = first * (length-1)*((int) Math.pow(10, length - 2));


到此1346~ 21345中1出现的次数已经统计完了,递归统计1345、345、45和5,然后累加即可得到结果。


完整代码如下:

public class Solution {
	public int NumberOf1Between1AndN_Solution(int n) {
		int first, length;
		int numOtherDigits, numRecursive, numFirstDigit;
		String str = String.valueOf(n);

		first = str.charAt(0) - '0';
		length = str.length();

		if (1 == length && 0 == first)
			return 0;
		if (1 == length && first > 0)
			return 1;

		// 最高位出现1的次数
		if (first > 1) {
			numFirstDigit = (int) Math.pow(10, length - 1);
		} else {
			numFirstDigit = 1 + Integer.valueOf(str.substring(1));
		}
		
		// 其余位 出现1的次数
		numOtherDigits = first * (length-1)*((int) Math.pow(10, length - 2));
		
		// 递归处理
		numRecursive = NumberOf1Between1AndN_Solution(Integer.valueOf(str.substring(1)));

		return numFirstDigit+numOtherDigits+numRecursive;
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值