1的数目

这是题目:

给定一个十进制正整数 N,写下从1 开始,到 N的所有整数,然后数一下其中出现的所有“1”的个数


其实这个问题,我们可以暴力的去实现它,不过时间效率会是一个很大的问题


public int sum1(int n)
	{

		int iNum = 0;

		int count = 0;
		
		for (int i = 1; i <= n; i++)
		{
			iNum = 0;
			
			int t = i;
			while (t != 0)
			{
				iNum += (t % 10 == 1) ? 1 : 0;
				t /= 10;
			}
			count += iNum;
		}
		
		return count;
	}


他的时间复杂度会是 O(N * log2 N),当n一大,这会是一个可怕的问题


当然,这个问题也可以用巧妙的方法解决,一个数的位数上的1的个数总是和这个数的高位和地位有关的,如34232,百位2的高位为34,低位为32,这可判断这个是百位中1的个数肯定是(34+1)*100,由于每个都是100-199中这100个数出现100,同理可推到其他位数


请看代码实现

public int sum(int n)
	{
		//低位
		int lowNum = 0;
		//高位
		int hightNum = 0;
		//当前位
		int currNum = 0;
		//为权重,1,10,100...
		int factor = 1;

		int count = 0;

		while (n / factor != 0)
		{
			lowNum = n - (n / factor) * factor;
			hightNum = n / (factor * 10);
			currNum = (n / factor) % 10;

			switch (currNum)
			{
			case 0:
				count += hightNum * factor;
				break;

			case 1:
				count += hightNum * factor + (lowNum + 1);
				break;

			default:
				count += (hightNum + 1) * factor;
				break;

			}

			factor *= 10;
		}

		return count;

	}

改进后,时间复杂度为O(Len)

可见,对时间效率的提升的多么明显


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值