题目:在给定的范围内,例如1~99999,找出吉祥数字,满足的条件为:全部数字必须由6或者8构成,如66666,66668,668,…
1.一开始想的很杂,考虑了效率:把要查找的数转化成String再转化成char数组,逐个跟“6”,“8”比较。但是这样的话,用String会创建许多对象,会消耗许多内存资源。
2.想到了将每个需要判断的位数都转化成各位上的数,然后%10,得到这个值跟6和8比较。并且做了一些细节上的优化:
将变量都声明在for循环外边,减少系统在运行期间创建对象的个数,节约系统资源。
3.像这种特定的需求,例如本文的吉祥数,可以考虑采用二叉树的形式进行编码,效率极高(未给出具体代码)。
代码如下:
public class JiXiangSearch {
public static void main(String[] args) {
//下边两个是主要思路的测试代码,有需要的可以解除注释简单测试一下。
/*System.out.println(448%10);
System.out.println((448/10)%10);*/
//正式部分开始,首先声明一些需要用到的变量,降低系统资源消耗
int n = 0; //用来接收要查找的数调用toString方法后的长度值
int temp=0; //用来接收—10的幂值
int result=0; //用来接收i/temp后i的值
for(Integer i=1;i<=99999;i++) {
//用字符串长度的形式来表示i是几位数
n = i.toString().length();
//这个for循环的目的是为了逐位的判断i的每个位数上的值是不是6或者8
for (int j = 0; j <=n-1; j++) {
//用来复制i的值,保证i的值在计算过程中不直接参与,不发生变化。
int copy = i;
//Math类的一个方法求一个数的幂,返回值是double类型,需要强制类型转换
temp = (int)(Math.pow(10, j));
//每次进入循环除以10的幂次方,将要比较的位数转换成个位数。
result = (copy/temp)%10;
if(result==6||result==8){ //吉祥数判断,判断当前个位上的数是不是吉祥数字。
//判断到最后一位,依然成立,输出i的值,
if(j==n-1) {
System.out.print(i + " ,");
}
}else{
break ;
}
}
}
}
}
测试结果如下所示:
"C:\Program Files\Java\jdk1.8.0_144\bin\java"
6 ,8 ,66 ,68 ,86 ,88 ,666 ,668 ,686 ,688 ,866 ,868 ,886 ,888 ,6666 ,6668 ,6686 ,6688 ,6866 ,6868 ,6886 ,6888 ,8666 ,8668 ,8686 ,8688 ,8866 ,8868 ,8886 ,8888 ,66666 ,66668 ,66686 ,66688 ,66866 ,66868 ,66886 ,66888 ,68666 ,68668 ,68686 ,68688 ,68866 ,68868 ,68886 ,68888 ,86666 ,86668 ,86686 ,86688 ,86866 ,86868 ,86886 ,86888 ,88666 ,88668 ,88686 ,88688 ,88866 ,88868 ,88886 ,88888 ,
Process finished with exit code 0
写到这里的时候我思考了一个问题,如何才能在比较更少的情况下查询出所有要查找的数字,
例如:如果将内层循环从最高位开始比较,这样如果最高位不符合要求,会减少很多不必要进行的判断,尝试修改代码如下:
我用九位数测试了一下,结果发现从最高位往最低位走的话,比上面的方式时间还要长,这里有些疑问,不知道为什么?
思路二:只查询6666-8888之间的数,去做一下试验:
//正式部分开始,首先声明一些需要用到的变量,降低系统资源消耗
int n = 0; //用来接收要查找的数调用toString方法后的长度值
int temp = 0; //用来接收—10的幂值
int result = 0; //用来接收i/temp后i的值
String[] str = {"1","11","111","1111","11111","111111","1111111","11111111","111111111"};
for(Integer i=1;i<=999999999;i++) {
//用字符串长度的形式来表示i是几位数
n = i.toString().length();
int toInt = Integer.parseInt(str[n-1]);
if(i>=6*toInt&&i<=8*toInt){
//这个for循环的目的是为了逐位的判断i的每个位数上的值是不是6或者8
for (int j = n-1; j >=0; j--) {
//用来复制i的值,保证i的值在计算过程中不直接参与,不发生变化。
int copy = i;
//Math类的一个方法求一个数的幂,返回值是double类型,需要强制类型转换
temp = (int)(Math.pow(10, j));
//每次进入循环除以10的幂次方,将要比较的位数转换成个位数。
result = (copy/temp)%10;
if(result==6||result==8){ //吉祥数判断,判断当前个位上的数是不是吉祥数字。
//判断到最后一位,依然成立,输出i的值,
if(j==0) {
System.out.print(i + " ,");
}
}else{
break ;
}
}
}else{
continue;
}
}
结果显示在没有进行判断之前,九位数需要进行133336ms,优化以后需要87610ms,节省了1/3的时间。
请各位大佬路过时候指点一下文章中红色字体,我不是太懂!!!谢谢。
做完这道题有了一些感想,算法的极致大概就是只让计算机查找或者计算工程师们想要查找的东西吧,除此之外的数据
由工程师负责全部排除掉。节约时间,提高效率。 ——我认为算法非常有意思!