首页 > 代码库 > 笔试算法题(20):寻找丑数 & 打印1到N位的所有的数

笔试算法题(20):寻找丑数 & 打印1到N位的所有的数

出题:将只包含2,3,5的因子的数称为丑数(Ugly Number),要求找到前面1500个丑数;

分析:

  • 解法1:依次判断从1开始的每一个整数,2,3,5是因子则整数必须可以被他们其中的一个整除,如果不包含任何其他因子则最终的结果为1;
  • 解法2:小丑数必然是某个大丑数的因子,也就是乘以2,3,或者5之后的值,所以可以利用已经找到的丑数来寻找下一个丑数,使用数组有序保存已经找到的丑 数,并且当前最大丑数值为M;用大于M/2的丑数乘以2得到M1,用大于M/3的丑数乘以3得到M2,用大于M/5的丑数乘以5得到M3,最后M1,M2 和M3中最小的数就是下一个丑数;
  • 此题让人联想到素数的求解,素数解法中是从小到大将等于小数倍数的数去除,最后剩下的就是素数;而本题是需要找到这些从小到大等于小数倍数的数,因为仅需2,3,5作为因子才能满足要求;

解题:

 1 bool IsUglyNumber(int n) {
 2         while(n%2 == 0)
 3                 n/=2;
 4         while(n%3 == 0)
 5                 n/=3;
 6         while(n%5 == 0)
 7                 n/=5;
 8 
 9         if(n == 1)
10                 return true;
11         else
12                 return false;
13 }
14 void BetterVersion(int limit) {
15         /**
16          * 创建数组array有序存储找到丑数
17          * */
18         int array[limit]; int length=2;
19         array[0]=1;array[1]=2;array[2]=3;
20         int M1, M2, M3,M;
21 
22         for(int j=0;j<limit-3;j++) {
23                 /**
24                  * 寻找大于已找到最大丑数,并且以小丑数和2,3或5
25                  * 为因子的丑数
26                  * */
27                 for(int i=0;i<length;i++) {
28                         if(array[i]*2>array[length]) {
29                                 M1=array[i]*2;break;
30                         }
31                 }
32                 for(int i=0;i<length;i++) {
33                         if(array[i]*3>array[length]) {
34                                 M2=array[i]*3;break;
35                         }
36                 }
37                 for(int i=0;i<length;i++) {
38                         if(array[i]*5>array[length]) {
39                                 M3=array[i]*5;break;
40                         }
41                 }
42                 /**
43                  * 使用最小值作为下一个丑数
44                  * */
45                 M=M1;
46                 if(M>M2) M=M2;
47                 if(M>M3) M=M3;
48                 array[++length]=M;
49                 printf("\n%d",M);
50         }
51 }

 

出题:输入数字N,N表示十进制数的位数,要求按序从1开始输出最大到N位的十进制数;

分析:

  • 解法1:N位数可能超出任何机器的最大数字范围;所以需要使用string,array或者创建一个大数类型来表示数字,然后模拟每次加1的运算,注意最后数字溢出N位数字的判断;
  • 解法2:同样使用string或者array表示数字,不同的是使用递归全排列N位数字,每位数字可能的取值是0-9,但是当N较大时系统栈也可能溢出;

解题:

 1 void printBigInt(int *array, int length, int index) {
 2         if(index == length) {
 3                 printf("\n");
 4                 for(int i=0;i<length;i++) {
 5                         if(array[i] !=0) {
 6                                 for(int j=i;j<length;j++)
 7                                         printf("%d",array[j]);
 8                                 break;
 9                         }
10                 }
11                 return;
12         }
13         for(int i=0;i<=9;i++) {
14                 array[index]=i;
15                 printBigInt(array,length,index+1);
16         }
17 }
18 void printBigInt(int length) {
19         int array[length];
20         for(int i=0;i<length;i++)
21                 array[i]=0;
22         printBigInt(array, length, 0);
23 }