本题要求写出前1500个仅能被2,3,5整除的数。
最初的想法是从1开始检验该数是否只能被2,3,5整除,方法是这样的,对于一个数,如果它能被2整除,就除以二,如果它能被3整除,就除以三,如果它能被5整除,就除以五,直到不能被2,3,5整除,看结果是不是1,如果是1就满足条件,否则不满足条件。但是第1500个数大约近10亿,显然是1s内不可以完成的。
然后仔细分析发现:满足条件的数是2^x*3^y*5^z,可以转换为这样的定义,定义一个集合,该集合中有元素1,如果x在集合中,那么2x,3x,5x也在集合中,其它数不再集合中。我们可以定义一个bool数组,初始化为false,从1开始设置为true,如果x为true,则2x,3x,5x设置为true,直到获得1500个true即可,典型的空间换时间的做法,但是这个空间也太大了!这个数组要开到近10亿才可以,显然是不可行的,内存用完了,可能都不够用。
顺着这个思路继续想下去,定义一个集合,该集合中有元素1,如果x在集合中,那么2x,3x,5x也在集合中,其它数不再集合中。按照这个思路走下去:
1
*2
*3
*5
从1*2 3 5中选一个最小的2放入到集合中,然后划掉*2,在2上加入*2
1
2
*3
*2
*5
从1*3 2*2中选一个最小的3放入到集合中,然后划掉1*3,在3上加入*2
1
2 3
*5
*2 *2
从1*5 2*2 3*2中选一个最小的4放入到集合中,然后划掉2*2,,加入2*3,在4上加入*2
1
2 3 4
*5
*3 *2 *2
从1*5 2*2 3*2 4*2中选一个最小的5放入到集合中,然后划掉1*5,加入5*2
2
3 4 5
*3
*2 *2 *2
从1*5 2*2 3*2中选一个最小的6放入到集合中,然后划掉2*3, 3*2,加入2*4 3*3 在6上加入*2
2
3 4 5 6
*4
*3 *2 *2 *2
以此类推,获得1500个数为止。
这样,我们可以这样实现:建立3个链表,待乘2的链表,待乘3的链表,待乘5的链表,将1放入3个链表中,然后判断3个链表中数据乘以各自要乘的数后哪个是最小的,比如此时1*2最小,将1放入*3的链表中,将新的数(2)加入到*2的链表中。如果最小的数是2*待乘2的链表中的数,则将该值从该链表中删除,该数加入到*3的链表中,将新得到的数加入到*2的链表中。如果最小的数是3*待乘3的链表中的数,则将该值从该链表中删除,该数加入到*5的链表中,将新得到的数加入到*2的链表中。如果最小的数是5*待乘5的链表中的数,则将该值从该链表中删除,该数不再加入到其它链表中,将新得到的数加入到*2的链表中。具体的实现可以从我的代码中获得,还有几个需要注意到细节:我的代码中用来很多if else 判断来提高效率,因为过程中出现很多值相等的情况。
链表的实现效率还是比数组的低,还有一种更简单的用数组的实现:只需要定义一个结果数组,和3个指针,分别代表待乘2的数,待乘3的数,待乘5的数,
1
*2
*3
*5
选出乘积最小的,加入到结果集中,相应指针右移
1 2
*3
*2
*5
选出乘积最小的,加入到结果集中,相应指针右移
1
2 3
*5
*2
*3
选出乘积最小的,加入到结果集中,相应指针右移
1
2 3 4
*5
*3 *2
选出乘积最小的,加入到结果集中,相应指针右移
1
2 3 4
*3 *2
*5
以此类推,直到获得1500的结果集。
带有详细注释的代码可以从
http://download.csdn.net/user/china8848/
获得。