码迷,mamicode.com
首页 > 其他好文 > 详细

数字之谜

时间:2014-05-15 04:13:31      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:面试题

数字之谜



问题1:从1,2,3,····,n,共有多少个1数字?

例子从1-12,共有5个1数字,结果如下

bubuko.com,布布扣


思路

我们知道最大值N,

暴力法:就是计算1-n的每个数里还有1数字的个数,然后相加即可,时间复杂度O(N*(每个数字的位数长度))

对于每个数,计算它还有1数字的个数的思路

先取来每位数字,对于一个数m,它的位数长度我们用length(int m)方法来求得

1)计算整数位数思路如下

// function 23: 计算一个整数有多少位数
// 输入: 一个整数
// 输出:整数的位数
int IntData_number(int N)
{
	int data = N;
	int length  = 0;
	while(data != 0)
	{
		data = data/10;
		length ++;
	}
	return length ;
}

2)抽取整数第i位操作思路如下

	n = pow(10.0,i);
	bit = ( N % n ) / (n/10) ;

3)然后对每一位判断是不是1即可

优化法:首先我们能得到最大数N的位数为length(用到的方法如上)

然后我们转换问题:数字的组合排列问题

思路如下



int f(int N)
{
	int result = 0;
	int length = 0;
	int bit = 0;
	int n = 0;
	int now = 0;

	if( N>0 )
	{
		// 对于长度为1 的数字处理
		if(N<=9)
			return 1;

		length = String::IntData_number(N);
		//对于长度>1的数字处理
			// 对个位处理
				// 如果个位是 0,则高位有( n/10 +1(算上0) - 1(因为个位是0,最大的数不能要))个选择
				if( N%10  ==  0 )
					result = N/10 ;
				// 否则 则高位有 ( n/10 +1(算上0))个选择
				else result = N/10 +1;

			// 对2 -(n-1)位处理
			for(int i = 2;i<length;i++)
			{	
				//获取第i位数字
					n = pow(10.0,i);
					bit = ( N % n ) / (n/10) ;
				//第i位为 0,则高位的选择为 N/ (10^i) +1-1(因为包括0,不包括最高位)
				//低位选择为 10^(i-1)
				if(bit == 0)
				{
					now = (N/n )*(n/10) ;
				}
				//第i位为1,则高位的选择为 N/ (10^i) +1-1(因为包括0,不包括最高位)
				//低位选择为 10^(i-1)
				//同时还得加上高位为最大时,低位上的选择N%(10^(i-1))+1(因为包括 0)
				else if(bit == 1)
				{
					now = (N/n )*(n/10) ;
					now += N % (n/10) +1;
				}
				//第i位>1,则高位的选择为 N/ (10^i) +1(因为包括0,包括最高位)
				//低位选择为 10^(i-1)
				else 
				{
					now = (N/n+1)*(n/10) ;
				}
				result += now ; 
			}

			// 对最后一位处理
			if(length > 1)
			{
				bit = N /(int)(pow(10.0,length-1));
				// 对于最后一位是 1,则其后面的数+1(因为包括0)
				if( bit==1 )
				{
					result += N % (int)(pow(10.0,length-1)) + 1;
				}
				// 否则 为 10^(n-1),每一个都有10个取值选择
				else if(bit > 1) 
				{
					result += (int)(pow(10.0,length-1));
				}
			}
	}
	//else cout<<"N<=0"<<endl;
	return result;
}


优化法运行结果


部分截图如下

bubuko.com,布布扣

程序注释 每一行第一个数为N,第二个数为问题答案


问题2:

对于问题1,求出f(N),现在问题求出f(N)= N时N的最大值

对于数学来说,N值会很大,有可能超出int最大值,也可能不超出,这个我也没法证明

我的思路是从int最大值逐渐减小然后求得符合条件的N值


思路:


		int i = numeric_limits<int>::max(),m;
		while(true)
		{
			m = f(i);
			if(i == m)
			{
				cout<<i<<"     "<<m<<endl;
				break;
			}
			i--;
		}

结果:

程序运行结果如下

bubuko.com,布布扣


即求出的最大值为途中所示。








数字之谜,布布扣,bubuko.com

数字之谜

标签:面试题

原文地址:http://blog.csdn.net/cqs_experiment/article/details/25689269

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!