在从1到n的正数中1出现的次数

题目:输入一个整数n,求从1nn个整数的十进制表示中1出现的次数。

例如输入12,从112这些整数中包含1的数字有11011121一共出现了5次。

最简单思路,就是从1-n一个刚数字进行判断然后计数即可,

int NumberOf1BeforeBetween1AndN_Solution1(unsigned int n)
{
	int number = 0;

	// Find the number of 1 in each integer between 1 and n
	for(unsigned int i = 1; i <= n; ++ i)
		number += NumberOf1(i);

	return number;
}

int NumberOf1(unsigned int n)
{
	int number = 0;
	while(n)
	{
		if(n % 10 == 1)
			number ++;

		n = n / 10;
	}

	return number;
}

这个思路有一个非常明显的缺点就是每个数字都要计算1在该数字中出现的次数,因此时间复杂度是O(n)。当输入的n非常大的时候,需要大量的计算,运算效率很低。这里引入新的思路,以n=21345为例,可以分成两部分1-1345和1346-21345,先分析1236-21345这一部分20000个数字,1-1345迭代即可。

对于1236-21345分析1出现的次数,可以分两种情况

a 1在最高位(万),一共在10000-19999中出现过,一共10^4次,当然这是在这个最高位数字2大于1的情况下,如 最高位原数字就是等于1,如11345则此时统计最高位1出现次数很明显就只有1345+1次

b 1在其他为(后四位),选取一位为1,有len-1=4种选法,每种指定1后,剩下3位有10^3种情况,再考虑最高位后1出现此时最高位数字2×4×10^3。

剩下的对1-1345类似分析即可。

代码:

int powerbase10(int n){
int res=1;
for(int i=0;i<n;i++)
    res*=10;
return res;
}//10^n
int numberof1(string str){
if(str.size()<1)return 0;
int first=str[0]-'0';
unsigned int len=static_cast<unsigned int>(str.size());
if(len==1&&first==0)return 0;
if(len==1&&first>0){return 1;
                    }
int num_first=0;
int num_other=first*(len-1)*powerbase10(len-2);
int numrecursive=numberof1(str.substr(1));
if(first>1)num_first=powerbase10(len-1);
else if(first==1)num_first=atoi(str.substr(1).c_str())+1;
return num_first+num_other+numrecursive;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值