2018.1.23 第二第八题

两道题:

一、

 题目:求一个数的阶乘后面有几个0

  11! = 39916800,所以后面有两个0

  要求时间复杂度小于O(log N) 

 思路:

 因为有时间复杂度的限制,肯定不能直接算出阶乘

 想一想后发现所有末尾出现0的肯定和5有关的,都是5乘一个偶数或者5的倍数乘一个偶数

 如5*2 ,15*2,35*2或者直接包括类似10、100的。

 但是不用组合的得出的0的个数也是不一样的。

 如只是5的倍数而不是5的高次幂的倍数,只出现一个0:如5*2、15*2、10*2;

 5的平方的倍数出现两个0:如25*4, 50*4,75*4;

 以此类推:

 5的立方的倍数出现3个0:如125*8、250*4等

 于是有了思路,0的个数n=n/5+n/25+n/125+ ......;

 于是可以写函数了 ,写了一个递归函数

int zeroNumber(int n)
{
	if(n<5)
		return 0;
	return n/5+zeroNumber(n/5);
}
 第一层递归先算出5的倍数,第二层算出25的倍数的个数.........知道有一层为0,然后全加起来就是结果,

 想了想非递归算法也很简单:

int xz(int n)
{
	while(n!=0)
	{
		x=x+n/5;
		n=n/5;
	}
	return x;
}

 解释:x为0的个数

 这道题的重点在于转化问题,把0的个数转化为阶乘中5的n次幂的倍数的个数的问题。

二、

 字符串偏移

偏移量为n

要求空间复杂度为O(1)

例子:

Given "abcdefg".

offset=0 => "abcdefg"
offset=1 => "gabcdef"
offset=2 => "fgabcde"
offset=3 => "efgabcd"
乍一看感觉很简单。

但是想了很久才写出代码:

因为空间复杂度为确定为O(1);

所以只能一个字符一个字符的转移,并且转移的同时保存

这样的话只能按照转移的顺序执行程序,即abcdefg偏移量为3的话

a到d

d到g

g到c

c到f.

..

直到全部完成

但是!!!!

例如abcdef 偏移量为3

就会进入一个循环

a到d

d到a

永远不会完成

所以需要加判断如果回到了一开始的地方并且没有完成,就往后走一位继续运算

判断完成只需用一个计数器即可,而判断回到一开始也只需要保存一下第一个就好。

满足空间复杂度为O(1)

代码如下:

void sz(string &str,int n)
{
	int m=str.length();
	if(m==0)return;
	if(n==0)return;
	char x=str[0];
	char y;
	n=n%m;
	int i=0;
	int count=0;
	int c=0;
	while(1)
	{
		y=str[(i+n)%m];
		str[(i+n)%m]=x;
		x=y;
		count++;
		if((i+n)%m==c)
		{
			c++;
			i++;
			x=str[(i+n)%m];
		}
		if(count==m)
			break;
		i=i+n;
	}
	return;
}
有些看上去很简单的东西,还真没有想的那么简单。。。。

一开始总是按照顺序做.后来发现那样的话,因为偏移量的不同,前一个字符不到下一个字符的位置,所以需要很多的不确定空间

所以做不出来....

后来就想到了分组转移,按照前一个字符到下一个字符的位置的顺序转移就很简单了





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值