题目
到x星球旅行的游客都被发给一个整数,作为游客编号。
x星的国王有个怪癖,他只喜欢数字 3, 5 和 7 。
国王规定,游客的编号如果只含有因子:3 , 5, 7, 就可以获得一份奖品。
我们来看前10个幸运数字是:
3 5 7 9 15 21 25 27 35 45
因而第11个幸运数字是:49
小明领到了一个幸运数字 59084709587505。
他去领奖的时候,被要求准确地说出这是第几个幸运数字,否则领不到奖品。
请你帮小明计算一下,59084709587505是第几个幸运数字。
分析
我们先来看当数字较小的时候采用的可靠的笨办法。
从小到大搜索整数,当它只含有 因子3, 5, 7, 就把它记录在数组中。
判断是否只含有因子 3 5 7,只要不断的地除以3 5 7, 看看最后剩下的是不是 1 即可。
用这个办法对付上面那个大数,一般电脑肯定不行。
更高效的算法:
我们可不可以设法去生成那个幸运数的数列呢?、
有没有注意到,数列中的每个数都是数列前边的数乘以3, 5 或 7 得到的。
因而,只把开始 3 个位置添上3, 5, 7, 后边的就都可以算出来啦!
难度在于:应该把前边哪个位置上的数乘以多少,放入到后边的哪个位置呢?
注意会有重复噢。比如 3 x 5, 5 x 3
可能会有很多实现的手段。
比如方案一:
用一个指针,从 3 开始,往后扫。
对扫过的每一个数,分别乘以 3 5 7,得到的 3 个数插入到队列中合适位置。
实际上是二分法进行的经典的插入排序。
虽然说,尾巴上的一些数的序号可能不靠谱,但指针扫过的那些肯定是靠谱的。
还有更好的方案二:
分别用三个指针,对指针指向的数字分别进行乘3, 乘5, 乘7 的操作。
3 个乘积 pk 一下,谁最小,这个数就填入到队尾。
产生这个数的指针向前移动。
代码
先上个笨的
//problem004
import java.util.*;
public class A
{
static List<Integer> f(int num){
List<Integer> lst = new ArrayList<Integer>();
for(int i=3; lst.size()<num; i++){
int n = i;
while(n%3==0) n /= 3;
while(n%5==0) n /= 5;
while(n%7==0) n /= 7;
if(n==1) lst.add(i);
}
return lst;
}
public static void main(String[] args){
System