笔试题练习(五)

来源:互联网 发布:飞扬软件维护费 编辑:程序博客网 时间:2024/05/21 23:34

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

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


/**
 * 
 * 
@author phinecos
 * 
@since 2005-05-27
 
*/
public class test 
{
    
private static String multipy(String num1, String num2)
    {
//大数乘法
        String result = "0";
        
int i,j,n1,n2;
        
int len1 = num1.length();
        
int len2 = num2.length();
        
if (len1 < len2)
        {
            
for (i = len1 -1; i >=0--i)
            {
                n1 
= num1.charAt(i) - '0';
                String sum 
= "0";
                
for (j = 0; j < n1; ++j)
                {
                    sum 
= add(sum,num2);
                }
                StringBuilder tmpSB 
= new StringBuilder(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';
                String sum 
= "0";
                
for (j = 0; j < n2; ++j)
                {
                    sum 
= add(sum,num1);
                }
                StringBuilder tmpSB 
= new StringBuilder(sum);
                
for (j = i; j < len2 -1++j)
                {
                    tmpSB.append(
"0");
                }
                result 
= add(result,tmpSB.toString());
            }
        }

        
return result;
    }    
    
private static String add(String num1, String num2)
    {
        String result 
= "";
        
int len1 = num1.length();
        
int len2 = num2.length();
        
int nAddOn = 0;
        
int i,j,n1,n2,sum;
        StringBuilder sb 
= new StringBuilder();
        
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);
            }
        }
        
else if (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();
        
return result;
    }
    
private static String factorial(int n)
    {
        String result 
= "1";
        
for (int i = n; i >= 2--i)
        {
            result 
= multipy(result,String.valueOf(i));
        }
        
return result;
    }
    
private static int countNFactZeroes(int n)
    {
        String result 
= factorial(n);//N!
        System.out.println(result);
        
int count = 0;
        
for (int i = result.length()-1; i >= 0--i)
        {
            
if (result.charAt(i) == '0')
            {
                
++count;
            }
            
else
                
break;
        }
        
return count;
    }
    
public static void main(String[] args) throws Exception
    {
        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

    private static int countNFactZeroes2(int n) 
    {
        
int i,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;
            } 
        } 
        
return result; 
    }

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

    private static int countNFactZeroes3(int n) 
    {
        
int pow5,result=0
        
for(pow5 = 5; pow5 <= n; pow5 *= 5// 此处的循环次数为LOG5(N)
        {
            result 
+= n / pow5; 
        } 
        
return result; 
    }

设最大数为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即相加便得到以下算法

    private static int countNFactZeroes4(int n) 
    {
        
int result=0
        
int m = n/5;
        
while (m > 0)
        {
            result 
+= m;
            m 
= m/5;
        }
        
return result; 
        }

等比数列的项数为log5(N)即为循环的次数故复杂度为log5(N)

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

/************************************************************************/
/* Author: phinecos Date:2009-05-27                                                                     */
/************************************************************************/
#include 
<iostream>
#include 
<cassert>
using namespace std;

int StringToInt(const char* str)
{
//考虑八进制,十六进制,十进制
    assert(str != NULL);
    assert(strlen(str) 
!= 0);

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

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

/************************************************************************/
/* Author: phinecos Date:2009-05-27                                                                     */
/************************************************************************/
#include 
<iostream>
using namespace std;

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

char* merge(char a[], int n, char b[],int m)
{
    
char *= new char[m+n];
    
int i,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中不存在的加入新数组
    char ch; 
    
for (i = 0; i < 256++i)
    {
        
if (isExist[i] == true)
        {
            ch 
= (char)i;
            c[k
++= ch;
        }
    }
    c[k] 
= '/0';
    
return c;

}
int main()
{
    
char a[] = {'a','c','4','s','v','y','Y','C','E'};
    
char b[] = {'c','y',',','u','r'};
    
int n = sizeof(a) / sizeof(char);
    
int m = sizeof(b) / sizeof(char);
    
char *= merge(a,n,b,m);
    cout 
<< c << endl;
    delete [] c;
    
return 0;
}

 

原创粉丝点击