【求所有的4位吸血鬼数字】
1、什么是吸血鬼数字?
吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序。——百度百科
由于问题只是4位的吸血鬼数字,那么就很明确了,我们需要找的是某一个数字“abcd”,符合以下条件:
- abcd = ab*cd
- 以两个0结尾的数字是不允许的
2、方法思考
2.1、各种方法
关于这个问题,各种博客论坛都已有了许许多多的解决方法,以下是我认为比较简洁清晰的解释:
2.2、关于上述第二个解决方法的解析
这是我搜集到的需要执行运算最少的方法,下面给出我的理解:
2.2.1、方法详情
import java.util.Arrays;
/*
* 吸血鬼数字;
* 一个偶位数字(本题要求为4位),可以拆分为2个该数字位/2的数字的乘积,顺序不限。
*/
public class VampireNumbers {
public static void main(String[] arg) {
String[] ar_str1, ar_str2;
int sum = 0;
int minInt;
int maxInt;
int num;
int time = 0;
for (int i = 10; i < 100; i++) {
minInt = Math.max(1000 / i, i + 1);
maxInt = Math.min(10000 / i, 100);
for (int j = minInt; j < maxInt; j++) {
num = i * j;
//
if (num % 100 == 0 || (num - i - j) % 9 != 0) {
continue;
}
time++;
ar_str1 = String.valueOf(num).split("");
ar_str2 = (String.valueOf(i) + String.valueOf(j)).split("");
Arrays.sort(ar_str1);
Arrays.sort(ar_str2);
if (Arrays.equals(ar_str1, ar_str2)) {
sum++;
System.out.println("第" + sum + "组: " + i + "*" + j + "=" + num);
}
}
}
System.out.println("共找到" + sum + "组吸血鬼数");
System.out.println("运算次数:" + time);
}
}
2.2.2、方法详解
1、开头的双层循环部分:
- 先简单的解释
maxInt = Math.min(10000 / i, 100);
,这个式子中min方法的第二个参数100是作为最大值限制参数j的,第一个参数中的10000/i是为了限制不让i*j大于4位数。但是因为i的范围是10~99,得到的最小值一直是100,所以这段代码也完全可以直接写成maxInt = 100;
。 - 其次是关于
minInt = Math.max(1000 / i, i + 1);
的作用。首先其中的1000 / i
的作用就是保证i * j
的结果一定能达到四位数,这也起到了筛选的作用,i + 1
则是保证了所有的遍历不会出现类似于发现aaaa=xymn的情况后又有aaaa=mnxy的情况。
2、双层循环中的if条件:
num % 100 == 0
:由于吸血鬼数字不允许出现两个两位数都以0结尾的情况,而这种情况导致的结果就是i*j必然是100的倍数,所以只要把着各种情况筛选出去就能避免,(num - i - j) % 9 != 0
:由于四位数abcd是1000a+100b+10c+d,而i和j都是10x+y的格式,那么无论是什么数字的组合,用num - i - j
计算的结果都必然是9的倍数,所以把不是的情况筛选出去即可。
3、确认得到的结果:
通过上述的筛选后,基本已经完成了大部分数字的筛选,现在遍历得到的数字都是符合条件的,只要找到所用数字相同的即可。
- 将四位数转化为字符串并生成字符串数组,将两个两位数转化为字符串并连接,同样生成字符串数组。
ar_str1 = String.valueOf(num).split("");
ar_str2 = (String.valueOf(i) + String.valueOf(j)).split("");
- 将两个字符串数组分别排序
Arrays.sort(ar_str1);
Arrays.sort(ar_str2);
- 排序后进行比较,如果相同则表明是一组吸血鬼数字:
if (Arrays.equals(ar_str1, ar_str2))