`
dato0123
  • 浏览: 914557 次
文章分类
社区版块
存档分类
最新评论

笔试题练习(五)

 
阅读更多

1, 对任意输入的正整数N,编写程序求N!的尾部连续0的个数,并指出计算复杂度。如:18!=6402373705728000,尾部连续0的个数是3。(不用考虑数值超出计算机整数界限的问题)

解法1:(直接大数计算N!

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
/**
*
*
@authorphinecos
*
@since2005-05-27
*/
publicclasstest
{
privatestaticStringmultipy(Stringnum1,Stringnum2)
{
//大数乘法
Stringresult="0";
inti,j,n1,n2;
intlen1=num1.length();
intlen2=num2.length();
if(len1<len2)
{
for(i=len1-1;i>=0;--i)
{
n1
=num1.charAt(i)-'0';
Stringsum
="0";
for(j=0;j<n1;++j)
{
sum
=add(sum,num2);
}
StringBuildertmpSB
=newStringBuilder(sum);
for(j=i;j<len1-1;++j)
{
tmpSB.append(
"0");
}
result
=add(result,tmpSB.toString());
}
}
else
{
for(i=len2-1;i>=0;--i)
{
n2
=num2.charAt(i)-'0';
Stringsum
="0";
for(j=0;j<n2;++j)
{
sum
=add(sum,num1);
}
StringBuildertmpSB
=newStringBuilder(sum);
for(j=i;j<len2-1;++j)
{
tmpSB.append(
"0");
}
result
=add(result,tmpSB.toString());
}
}

returnresult;
}
privatestaticStringadd(Stringnum1,Stringnum2)
{
Stringresult
="";
intlen1=num1.length();
intlen2=num2.length();
intnAddOn=0;
inti,j,n1,n2,sum;
StringBuildersb
=newStringBuilder();
for(i=len1-1,j=len2-1;i>=0&&j>=0;--i,--j)
{
n1
=num1.charAt(i)-'0';
n2
=num2.charAt(j)-'0';
sum
=n1+n2+nAddOn;

if(sum>=10)
{
nAddOn
=1;
}
else
{
nAddOn
=0;
}
sb.append(sum
%10);
}
if(len1>len2)
{
for(;i>=0;--i)
{
n1
=num1.charAt(i)-'0';
sum
=n1+nAddOn;
if(sum>=10)
{
nAddOn
=1;
}
else
{
nAddOn
=0;
}
sb.append(sum
%10);
}
}
elseif(len2>len1)
{
for(;j>=0;--j)
{
n2
=num2.charAt(j)-'0';
sum
=n2+nAddOn;
if(sum>=10)
{
nAddOn
=1;
}
else
{
nAddOn
=0;
}
sb.append(sum
%10);
}
}

if(nAddOn>0)
{
sb.append(nAddOn);
}

sb.reverse();
result
=sb.toString();
returnresult;
}
privatestaticStringfactorial(intn)
{
Stringresult
="1";
for(inti=n;i>=2;--i)
{
result
=multipy(result,String.valueOf(i));
}
returnresult;
}
privatestaticintcountNFactZeroes(intn)
{
Stringresult
=factorial(n);//N!
System.out.println(result);
intcount=0;
for(inti=result.length()-1;i>=0;--i)
{
if(result.charAt(i)=='0')
{
++count;
}
else
break;
}
returncount;
}
publicstaticvoidmain(String[]args)throwsException
{
System.out.println(countNFactZeroes(
18));
}
}

解法2连续K0,则说明是10^K的倍数,即(2×5)^ K= 2^K× 5^K;待求的数为N*(N-1)(N-2)………1,由于每两个数至少可以分解出122肯定比5多,因此K的个数取决于上式的分解因子中有几个5的问题;能拆解出5的只可能是5的倍数,而能拆解出多少个5则看这个数是5的几次方的倍数了。时间复杂度是Onlogn

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->privatestaticintcountNFactZeroes2(intn)
{
inti,j,result=0;
for(i=5;i<=n;i+=5)//循环次数为n/5
{//只针对可以整除5的分解因子
for(j=i;j%5==0;j/=5)//此处的最大循环次数为LOG5(N)
{//当前分解因子可以整除几个5
++result;
}
}
returnresult;
}

解法3N不变,pow55的幂递增,此算法的思想是求出N以内所有被5整除的数的个数,所有被25整除的个数(在5的基础上多出了一个5因子),所有被125整除的个数(在25的基础上多出了一个5因子)。。。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->privatestaticintcountNFactZeroes3(intn)
{
intpow5,result=0;
for(pow5=5;pow5<=n;pow5*=5)//此处的循环次数为LOG5(N)
{
result
+=n/pow5;
}
returnresult;
}

设最大数为N, 5^(n+1) >N >=5^n
[N/5]+[N/(5^2)]+[N/(5^3)]+...+[N/(5^n)]
即为连续0的个数

上述式子的项数为log5(N),即为循环的次数,故复杂度为log5(N)
解法4:由解法3可得如下:

[N/5]+[N/(5^2)]+[N/(5^3)]+...+[N/(5^n)]

=[N/5]+[[N/5]/5]+[[[N/5]/5]/5]+...+[。。。]

=A1+[A1/5]+[A2/5]+...+[An-1/5]

即上述各项构成等比数列An=An-1/5等比为1/5

即对A1反复除5只要其大于0即相加便得到以下算法

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->privatestaticintcountNFactZeroes4(intn)
{
intresult=0;
intm=n/5;
while(m>0)
{
result
+=m;
m
=m/5;
}
returnresult;
}

等比数列的项数为

log5(N)即为循环的次数故复杂度为log5(N)

2,题目:请编写一个 C 函数,该函数将给定的一个字符串转换成整数

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->/************************************************************************/
/*Author:phinecosDate:2009-05-27*/
/************************************************************************/
#include
<iostream>
#include
<cassert>
usingnamespacestd;

intStringToInt(constchar*str)
{
//考虑八进制,十六进制,十进制
assert(str!=NULL);
assert(strlen(str)
!=0);

intresult=0;
intsign=1;//符号位
intradix=10;//默认是进制
constchar*p=str;
if(*p=='-')
{
//负数
sign=-1;
++p;
}
if(*p=='0')
{
//以'0'开头,或者是八进制,或者是十六进制
if((*(p+1)=='x')||(*(p+1)=='X'))
{
//16进制
radix=16;
p
+=2;//跳过'0x'
}
else
{
//八进制
radix=8;
++p;//跳过'0'
}
}
while(*p!='/0')
{
if(radix==16)
{
//16进制
if(*p>='0'&&*p<='9')
{
result
=result*radix+*p-'0';
}
else
{
//字母
inttmp=toupper(*p);//大写化
result=result*radix+tmp-'A'+10;
}
}
else
{
//8或进制,不含字母
result=result*radix+*p-'0';
}
++p;
}
returnresult*sign;
}
intmain()
{
cout
<<StringToInt("-355643")<<endl;
cout
<<StringToInt("-0x200")<<endl;
cout
<<StringToInt("-0123")<<endl;
cout
<<StringToInt("-0x7FFFFFFF")<<endl;
return0;
}

3,已知两个字符数组,char a[m],b[n],m>n>1000,写程序将a中存在,但b中不存在的元素放入字符数组c中,并说明算法的时间复杂度

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->/************************************************************************/
/*Author:phinecosDate:2009-05-27*/
/************************************************************************/
#include
<iostream>
usingnamespacestd;

boolisExist[256]={false};//256个字符是否存在的标志

char*merge(chara[],intn,charb[],intm)
{
char*c=newchar[m+n];
inti,k=0;
//判断数组a中哪些字符存在
for(i=0;i<n;++i)
{
isExist[a[i]]
=true;
}
//判断数组b中哪些字符存在
for(i=0;i<m;++i)
{
if(isExist[b[i]]==true)
{
isExist[b[i]]
=false;
}
}
//a中存在,b中不存在的加入新数组
charch;
for(i=0;i<256;++i)
{
if(isExist[i]==true)
{
ch
=(char)i;
c[k
++]=ch;
}
}
c[k]
='/0';
returnc;

}
intmain()
{
chara[]={'a','c','4','s','v','y','Y','C','E'};
charb[]={'c','y',',','u','r'};
intn=sizeof(a)/sizeof(char);
intm=sizeof(b)/sizeof(char);
char*c=merge(a,n,b,m);
cout
<<c<<endl;
delete[]c;
return0;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics