慢慢研究Thinking in Java
原题见Thinking in Java第四版 P75 练习10
找出四位数的所有吸血鬼数字
吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序.
以两个0结尾的数字是不允许的。←注意这行字
例如下列数字都是吸血鬼数字
1260=21*60
1827=21*87
2187=21*81
注意:以下代码为笨方法来解题
注意:以下代码是以初学者的视角来尽量解决问题,有错误多多包涵
注意:代码设计的东西只包括:for,int[] 无其他高深的知识,应该很轻松就可以看懂
注意:代码中莫名其妙蹦出来的66来自排列组合计算结果,详情请进
https://baike.baidu.com/item/%E6%8E%92%E5%88%97%E7%BB%84%E5%90%88/706498
选择排列查看相关计算方式
2
C =66
12
计算吸血鬼数的代码如下:
有点多,用了60行代码可以计算得出
package U4;
public class Exam4_8_10 {
public static void main(String[] args) {
for (int i=1000; i<10000; i++){
int[] k = new int[4];
int[][] l = new int[4][4];
int[] q = new int[12];
int count=0;
int z = i;
if(z%100 != 0){ //不允许出现00结尾的数字,出现直接跳过
for(int j=0; j<4; j++){ //把4位数字拆开
k[j] =z%10;
z = z/10;
}
for (int m=0; m<4; m++){ //把4个数字两两组合并放在一个数组里
for (int n=0; n<4; n++){
l[m][n] =k[m]*10+k[n];
}
}
for (int j=0 ;j<4; j++){ //去重,把自己乘自己的部分找出来
l[j][j] = 0;
}
for (int m=0; m<4; m++){ //然后去掉那部分,形成新数组
for (int n=0; n<4; n++){
if(l[m][n] != 0){
q[count] = l[m][n];
count++;
}
}
}
count =66; //66的由来是组合C2 12计算得66
int[] x = new int[count];
count = 0;
for (int m=11; m>=0; m--){ //计算拆分两数相乘的结果
for (int n=0; n<12; n++){
if (m == n){
break;
}
x[count] = q[n]*q[m];
count++;
}
}
for(int m=0; m<count; m++){ //来判断拆分出来的结果再乘回去
if(x[m]==i){ //如果乘回去的那么多数字里出现了原拆分数字,则吸血鬼数成立
System.out.println("该数字为吸血鬼数:"+x[m]);
break;
}
else {
continue;
}
}
}
else { //这是为了去除吸血鬼数的限制,不能出现00结尾
continue;
}
}
}
}
这里继续给出判断单个数字是否为吸血鬼数的代码。
该代码i为待判断数字,有需要可以自行修改。
下列代码中包含测试性输出。
package U4;
public class Exam_4_8_10_1 {
public static void main(String[] args) {
int i =2187;
int z = i;
int[] k = new int[4];
int[][] l = new int[4][4];
int[] q = new int[12];
int count=0;
System.out.println("输入数字:"+i);
for(int j=0; j<4; j++){
k[j] =i%10;
i = i/10;
}
for (int j=0; j<4; j++){
System.out.println("拆分数字:"+k[j]);
}
for (int m=0; m<4; m++){
for (int n=0; n<4; n++){
l[m][n] =k[m]*10+k[n];
}
}
for (int j=0 ;j<4; j++){
l[j][j] = 0;
}
for (int m=0; m<4; m++){
for (int n=0; n<4; n++){
if(l[m][n] != 0){
q[count] = l[m][n];
count++;
}
}
}
count =66;
int[] x = new int[count];
count = 0;
for (int m=11; m>=0; m--){
for (int n=0; n<12; n++){
if (m == n){
break;
}
x[count] = q[n]*q[m];
count++;
}
}
System.out.println("总数:"+count);
for(int m=0; m<count; m++){
if(x[m]==z){
System.out.println("该数字为吸血鬼数");
break;
}
else {
continue;
}
}
}
}
这里给出程序2,判断单个数字是否为吸血鬼数的sount:
输入数字:2187
拆分数字:7
拆分数字:8
拆分数字:1
拆分数字:2
总数:66
该数字为吸血鬼数
这里给出程序1,吸血鬼数1000~9999之间的列举结果:
该数字为吸血鬼数:1092
该数字为吸血鬼数:1207
该数字为吸血鬼数:1250
该数字为吸血鬼数:1260
该数字为吸血鬼数:1275
该数字为吸血鬼数:1278
该数字为吸血鬼数:1325
该数字为吸血鬼数:1368
该数字为吸血鬼数:1394
该数字为吸血鬼数:1395
该数字为吸血鬼数:1435
该数字为吸血鬼数:1458
该数字为吸血鬼数:1530
该数字为吸血鬼数:1612
该数字为吸血鬼数:1625
该数字为吸血鬼数:1640
该数字为吸血鬼数:1729
该数字为吸血鬼数:1827
该数字为吸血鬼数:1845
该数字为吸血鬼数:1932
该数字为吸血鬼数:2139
该数字为吸血鬼数:2187
该数字为吸血鬼数:2496
该数字为吸血鬼数:2604
该数字为吸血鬼数:2736
该数字为吸血鬼数:2950
该数字为吸血鬼数:3268
该数字为吸血鬼数:3456
该数字为吸血鬼数:3478
该数字为吸血鬼数:3750
该数字为吸血鬼数:3840
该数字为吸血鬼数:3864
该数字为吸血鬼数:3975
该数字为吸血鬼数:3984
该数字为吸血鬼数:4275
该数字为吸血鬼数:4736
该数字为吸血鬼数:5775
该数字为吸血鬼数:5776
该数字为吸血鬼数:6708
该数字为吸血鬼数:6786
该数字为吸血鬼数:6790
该数字为吸血鬼数:6880
该数字为吸血鬼数:7189
该数字为吸血鬼数:7296
该数字为吸血鬼数:7298
该数字为吸血鬼数:8190
该数字为吸血鬼数:8918
这里也给出Thinking in Java官方给出的答案:
public class VampireNumbers {
static int a(int i) {
return i/1000;
}
static int b(int i) {
return (i%1000)/100;
}
static int c(int i) {
return ((i%1000)%100)/10;
}
static int d(int i) {
return ((i%1000)%100)%10;
}
static int com(int i, int j) {
return (i * 10) + j;
}
static void productTest (int i, int m, int n) {
if(m * n == i) System.out.println(i + " = " + m + " * " + n);
}
public static void main(String[] args) {
for(int i = 1001; i < 9999; i++) {
productTest(i, com(a(i), b(i)), com(c(i), d(i)));
productTest(i, com(a(i), b(i)), com(d(i), c(i)));
productTest(i, com(a(i), c(i)), com(b(i), d(i)));
productTest(i, com(a(i), c(i)), com(d(i), b(i)));
productTest(i, com(a(i), d(i)), com(b(i), c(i)));
productTest(i, com(a(i), d(i)), com(c(i), b(i)));
productTest(i, com(b(i), a(i)), com(c(i), d(i)));
productTest(i, com(b(i), a(i)), com(d(i), c(i)));
productTest(i, com(b(i), c(i)), com(d(i), a(i)));
productTest(i, com(b(i), d(i)), com(c(i), a(i)));
productTest(i, com(c(i), a(i)), com(d(i), b(i)));
productTest(i, com(c(i), b(i)), com(d(i), a(i)));
}
}
}
//讲道理我没看多懂……不过看这个代码的精简程度,有一种高大上的感觉……
哦对,其中的去重的方法是二维数组,找到重复的改0,
然后判断是否为0之后,再取有用的数据放另外一个数组里,感觉这种方法可行,
免除了单个求费时费力的问题。
其实这两串代码花了我将近两个小时的时间去想
主要的时间耽误在了拆分,枚举上了。
ps:Thinking in Java P75 练习10
pss:今天写这个题目显得很吃力,果然这本书对于新手很不友好。
psss:这个程序写的问题很多,只能做到正常输出正确结果,后续我有时间可以做优化
pssss:也许可以节约不少计算时间(虽然现在也是两三秒内出结果就是)
psssss:Java学习任重而道远。