关于吸血鬼数字,网上有很多的版本,也有最佳实现方式。最近看Java编程思想,又看到了这道题目。于是准备用Java再实现一次,同时和别人代码比较一下,看看自己写的算法究竟有多差劲(汗。。。)
题目:吸血鬼数字是指位数为偶数的数字,可由一对数字相乘而得到,这对数字各包含乘积的一半位数的数字,以两个0结尾的数字是不允许的。 四位数吸血鬼数字示例:1260=21*60,1827=21*87,2187=27*81……
首先大致想了一下,从1000循环到9999,对于每一个数字判断是不是符合,如果是符合则输出。对于每一个4位数,把它看作4个数字,满足条件的一对数字必然是这4个数字的一种排列方式。4个数字排列方式共有 4 != 24 个,9000 * 24 = 216000
这个数字不是特别大,1s内计算机可以跑完,于是。。。我就没多想开开心心的跑去实践了。
敲了好长时间才把代码敲出来,主要是好长时间不练,全排列怎么实现的,记不清了(捂脸)
public class Practice10 {
public static void main(String[] args) {
//老规矩,循环
FullPermutation f = new FullPermutation("");
String s;
int num;
for(int i = 1000; i < 9999; ++i) {
if(i%100 == 0) {
continue;
}
f.setSrc(String.valueOf(i));
while((s = f.nextSequence()) != null) {
num = Integer.parseInt(s);
if(i == ((num/100) * (num%100))) {
System.out.println(i + " = " + num);
break;
}
}
}
}
}
/**
* ps:全排列不用写那么多没用的代码的,一个函数就实现了
* 主要是手贱,想把它写成个类(汗)
* */
class FullPermutation {
private char ch[];
private char temp[];
private int flag = 0;
FullPermutation(String s) {
ch = s.toCharArray();
flag = 0;
}
FullPermutation(char ch[]) {
this.ch = ch;
flag = 0;
}
FullPermutation(long number) {
ch = String.valueOf(number).toCharArray();
flag = 0;
}
public void setSrc(String s) {
ch = s.toCharArray();
flag = 0;
}
public String nextSequence() {
if(flag >= jc(ch.length)) {
return null;
}
int b = 0;
int len = ch.length;
int tf = flag;
int jctemp = 0;
temp = ch.clone();
for(int i = 0; i < len-1; ++i) {
jctemp = jc(len - i - 1);
b = tf / jctemp + i;
for(int j = b; j > i; --j) {
temp[j] ^= temp[j-1];
temp[j-1] ^= temp[j];
temp[j] ^= temp[j-1];
}
tf %= jctemp;
}
++flag;
return new String(temp);
}
public String findSequence(int index) {
if(index >= jc(ch.length)) {
return null;
}
int b = 0;
int len = ch.length;
int tf = index - 1;
int jctemp = 0;
temp = ch.clone();
for(int i = 0; i < len-1; ++i) {
jctemp = jc(len - i - 1);
b = tf / jctemp + i;
for(int j = b; j > i; --j) {
temp[j] ^= temp[j-1];
temp[j-1] ^= temp[j];
temp[j] ^= temp[j-1];
}
tf %= jctemp;
}
return new String(temp);
}
private int jc(int x) {
if(x == 1)
return 1;
return jc(x-1) * x;
}
}
那么久了,还是有敲代码不写注释的习惯。。。虽然知道不写注释过段时间自己就看不懂了,但就是懒得加啊啊啊。。。
最初程序运行,输出结果有点小问题,把重复的也输出了,打印结果语句后面加了一条break语句后解决。
说实话,跑出来结果还是蛮开心的,然后屁颠屁颠的跑去网上看别人代码,一看才发现自己的SB
在这题中 abcd 与 cdab 是等价的,所以。。。。。
对每一个数字的判断是否符合条件,是 4 * 3 = 12种排列方式,不是24种
一倍的差距,我TM。。。
而且12种排列可能,12行代码直接列举出来就行了,干嘛要费劲写个全排列啊ค(TㅅT)
然后又发现更好的写法,穷举两位数相乘,再排序判断结果满不满足。。。效率比我这个高多了。参考:java编程——吸血鬼数字(四位)
再后来又看到把效率提高数倍的最佳,经过数学分析的结果,可怕ค(TㅅT) 9的倍数
参考:JAVA实现的吸血鬼数字算法,高效率版本
稍微深入了解了下,类似这种性质的数字叫 傅利曼数