您的位置:首页 > 编程语言 > Java开发

java实现吸血鬼数字的三个想法(附官方答案)

2016-08-25 20:05 330 查看
自己写了一种方法,优化过后还可以,不过取巧。网上找了两种方法,从运行时间上来看比自己的方法慢

官方的一种方法,运行时间简直快到不可思议,真没法了。

1、第一个方法(我自己写的)

从四位数入手,大量if语句,都是复制粘贴的



2、第二个方法(网上的)

从2位数入手,但缺点是需要引入java.util.Arrays



3、第三个方法(网上的)

突然发现和第二个好像一样??但是要慢很多



4、第四个方法(官方的答案)

简直快到无解,找到了一个新的数学关系来优化!!



代码如下:

package com.thinkinjava.vampire;
import java.util.Arrays;
public class VampireNumber {
private static void showfournum1()
{
String string="";
int a1,a2,a3,a4;
int x1=0,x2=0;
char[] ch=new char[5];
for (int i=1260;i<=6880;i++)
{
if (i % 100 ==0)continue;
string=Integer.toString(i);
ch=string.toCharArray();
a1=((int)(ch[0])-48);
a2=((int)(ch[1])-48);
a3=((int)(ch[2])-48);
a4=((int)(ch[3])-48);
if (a1!=0&&a3!=0)
{
x1=a1*10+a2;
x2=a3*10+a4;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a1*10+a4;
x2=a3*10+a2;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}
if (a1!=0&&a2!=0)
{
x1=a1*10+a3;
x2=a2*10+a4;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a1*10+a4;
x2=a2*10+a3;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}
if (a1!=0&&a4!=0)
{
x1=a1*10+a2;
x2=a4*10+a3;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a1*10+a3;
x2=a4*10+a2;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}

if (a2!=0&&a3!=0)
{
x1=a2*10+a4;
x2=a3*10+a1;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a2*10+a1;
x2=a3*10+a4;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}
if (a2!=0&&a4!=0)
{
x1=a2*10+a3;
x2=a4*10+a1;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a2*10+a1;
x2=a4*10+a3;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}
if (a3!=0&&a4!=0)
{
x1=a3*10+a2;
x2=a4*10+a1;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
x1=a3*10+a1;
x2=a4*10+a2;
if (x1*x2==i){System.out.println(i+" =  "+x1+"*"+x2);continue;}
}

}
}
private static void showfournum2()
{
String[] ar_str1, ar_str2;
int sum = 0;
int from;
int to;
int i_val;
// 双重循环穷举
for (int i = 10; i < 100; i++) {
// j=i+1避免重复
from = Math.max(1000 / i, i + 1);
to = Math.min(10000 / i, 100);
for (int j = from; j < to; j++) {
i_val = i * j;
if (i_val % 100 == 0 || (i_val - i - j) % 9 != 0) {
continue;
}
ar_str1 = String.valueOf(i_val).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 + "=" + i_val);
}
}
}
System.out.println("共找到" + sum + "组吸血鬼数");
}
private static void showfournum3() { //
for (int i = 11; i < 100; i++) {
for (int j = i; j < 100; j++) {
int k = i * j;
String kStr = Integer.toString(k);
String checkStr = Integer.toString(i) + Integer.toString(j);
if (kStr.length() != 4)
continue;
char[] kChar = kStr.toCharArray();
char[] checkChar = checkStr.toCharArray();
Arrays.sort(kChar);
Arrays.sort(checkChar);
boolean isVampire = Arrays.equals(kChar, checkChar);
if (isVampire) {
System.out.println(i + " * " + j + " = " + k);
}
}
}
}
private static void showfournum4() { // 官方参考答案

int[] startDigit = new int[4];
int[] productDigit = new int[4];
for (int num1 = 10; num1 <= 99; num1++)
for (int num2 = num1; num2 <= 99; num2++) {
// Pete Hartley's theoretical result:
// If x·y is a vampire number then
// x·y == x+y (mod 9)
if ((num1 * num2) % 9 != (num1 + num2) % 9)
continue;
int product = num1 * num2;
startDigit[0] = num1 / 10;
startDigit[1] = num1 % 10;
startDigit[2] = num2 / 10;
startDigit[3] = num2 % 10;
productDigit[0] = product / 1000;
productDigit[1] = (product % 1000) / 100;
productDigit[2] = product % 1000 % 100 / 10;
productDigit[3] = product % 1000 % 100 % 10;
int count = 0;
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++) {
if (productDigit[x] == startDigit[y]) {
count++;
productDigit[x] = -1;
startDigit[y] = -2;
if (count == 4)
System.out.println(num1 + " * " + num2 + " : "
+ product);
}
}

} /*
* Output: 15 * 93 : 1395 21 * 60 : 1260 21 * 87 : 1827 27 * 81 :
* 2187 30 * 51 : 1530 35 * 41 : 1435 80 * 86 : 6880
*///:~
}

public static void main(String[] args) {
long start=System.currentTimeMillis();
// VampireNumber.showfournum1();
// VampireNumber.showfournum2();
// VampireNumber.showfournum3();
VampireNumber.showfournum4();
long time=System.currentTimeMillis()-start;
System.out.println("耗时"+time+"毫秒");

}
}


官方答案解析:

官方的答案从两位数入手

首先剔除了((num1 * num2) % 9 != (num1 + num2) % 9)

因为假设吸血鬼数字

num=a*1000+b*100+c*10+d=(a*10+b)*(c*10+d);

num1=(a*10+b);

num2=(c*10+d);

num-num1-num2=a*990+b*99=9*(a*110+b*11)

这个数可以被9整除,也就是说吸血鬼数字被9除的余数和两个基数的和被9除的余数相等。

所以不符合这个条件的都被剔除

然后这一段

int product = num1 * num2;
startDigit[0] = num1 / 10;
startDigit[1] = num1 % 10;
startDigit[2] = num2 / 10;
startDigit[3] = num2 % 10;
productDigit[0] = product / 1000;
productDigit[1] = (product % 1000) / 100;
productDigit[2] = product % 1000 % 100 / 10;
productDigit[3] = product % 1000 % 100 % 10;


巧妙地利用float到int的隐式转换得到了两基数的各个单个数字和两基数乘积的单个数字,放在两个数组里

然后

for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++) {

c111
if (productDigit[x] == startDigit[y]) {
count++;
productDigit[x] = -1;
startDigit[y] = -2;
if (count == 4)
System.out.println(num1 + " * " + num2 + " : "
+ product);
}
}


双层循环对比数组,如果全部相同(这里指两个集合相同,不管数组索引,所以需要16次比较),则符合条件。

分析下来,官方的答案主要是巧妙地利用隐式转换得到各个位数从而节省了大量时间

我的方法是把四位数变成字符串,在变成char数组,然后取到各个位数,这样调用Integer.toString()和toCharArray()就浪费了大量时间

如果把我的

string=Integer.toString(i);
ch=string.toCharArray();
a1=((int)(ch[0])-48);
a2=((int)(ch[1])-48);
a3=((int)(ch[2])-48);
a4=((int)(ch[3])-48);


改成

a1=i /1000;
a2=i %1000 /100;
a3=i %1000 %100/10;
a4=i%1000%100%10;


这样消耗的时间也是0毫秒,但是还是需要在循环次数上取巧。就是第一次运算,知道范围之后限定循环范围来减少循环次数

改进代码

private static void showfournum1()
{
String string="";
int a1,a2,a3,a4;
int x1=0,x2=0;
char[] ch=new char[5];
for (int i=1260;i<=6880;i++)
{
if (i % 100 ==0)continue;
/*string=Integer.toString(i); ch=string.toCharArray(); a1=((int)(ch[0])-48); a2=((int)(ch[1])-48); a3=((int)(ch[2])-48); a4=((int)(ch[3])-48);*/
a1=i /1000;
a2=i %1000 /100;
a3=i %1000 %100/10;
a4=i%1000%100%10;
if (a1!=0&&a3!=0)
{
x1=a1*10+a2;
x2=a3*10+a4;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a1*10+a4;
x2=a3*10+a2;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}
if (a1!=0&&a2!=0)
{
x1=a1*10+a3;
x2=a2*10+a4;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a1*10+a4;
x2=a2*10+a3;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}
if (a1!=0&&a4!=0)
{
x1=a1*10+a2;
x2=a4*10+a3;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a1*10+a3;
x2=a4*10+a2;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}

if (a2!=0&&a3!=0)
{
x1=a2*10+a4;
x2=a3*10+a1;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a2*10+a1;
x2=a3*10+a4;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}
if (a2!=0&&a4!=0)
{
x1=a2*10+a3;
x2=a4*10+a1;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a2*10+a1;
x2=a4*10+a3;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}
if (a3!=0&&a4!=0)
{
x1=a3*10+a2;
x2=a4*10+a1;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
x1=a3*10+a1;
x2=a4*10+a2;
if (x1*x2==i){System.out.println(i+" = "+x1+"*"+x2);continue;}
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: