Thinking In Java 里面吸血鬼数字题

首先解释一下吸血鬼数字:吸血鬼数字是指位数为偶数的数字,可由一对数字相乘而得到,这对数字各包含乘积的一半位数的数字,以两个0结尾的数字是不允许的。

四位数吸血鬼数字示例:1260=21*60,1827=21*87,2187=27*81……

先列出结果:一共7个:1260=21*60,1395=15*93,1435=41*35,1530=51*30,1827=87*21,2187=27*81,6880=86*80

方法一:

本方法是《Thinking in Java》的官方答案,由于所处章节很靠前,所以采用的遍历四位数方法,正向思维,即先有四位数,再拆分,四个数字组合相乘,若乘积与原数相等,则输出,并计算为一个吸血鬼数字。

  1. public class SearchforVampireThinkinginJava {
  2. // control/VampireNumbers.java
  3. // TIJ4 Chapter Control, Exercise 10, page 154
  4. /* A vampire number has an even number of digits and is formed by multiplying a
  5. * pair of numbers containing half the number of digits of the result. The
  6. * digits are taken from the original number in any order. Pairs of trailing
  7. * zeroes are not allowed. Examples include: 1260 = 21 * 60, 1827 = 21 * 87,
  8. * 2187 = 27  * 81. Write a program that finds all the 4-digit vampire numbers.
  9. * (Suggested by Dan Forhan.)
  10. */
  11. //  本方法是顺向思维,即先有四位数,再拆分,四个数字组合相乘,若乘积与原数相等,则输出,并计算为一个吸血鬼数字。TMJG添加此行并注释
  12. //  其实sum的结果为107976次,非常大,算法效率很低,并且出现了重复(6880 = 86 * 80,6880 = 80 * 86)。TMJG添加此行并注释
  13. static int sum=0;//记录调用判断的次数,TMJG添加此行并注释
  14. static int a(int i) {
  15. return i/1000;    //求千位数字,下同,TMJG添加此行并注释
  16. }
  17. static int b(int i) {
  18. return (i%1000)/100;
  19. }
  20. static int c(int i) {
  21. return ((i%1000)%100)/10;
  22. }
  23. static int d(int i) {
  24. return ((i%1000)%100)%10;
  25. }
  26. static int com(int i, int j) {   //形成10~99的两位数,TMJG添加此行并注释
  27. return (i * 10) + j;
  28. }
  29. static void productTest (int i, int m, int n) {
  30. sum++;
  31. if(m * n == i) System.out.println(i + " = " + m + " * " + n);
  32. }
  33. public static void main(String[] args) {
  34. for(int i = 1001; i < 9999; i++) {
  35. productTest(i, com(a(i), b(i)), com(c(i), d(i)));
  36. productTest(i, com(a(i), b(i)), com(d(i), c(i)));
  37. productTest(i, com(a(i), c(i)), com(b(i), d(i)));
  38. productTest(i, com(a(i), c(i)), com(d(i), b(i)));
  39. productTest(i, com(a(i), d(i)), com(b(i), c(i)));
  40. productTest(i, com(a(i), d(i)), com(c(i), b(i)));
  41. productTest(i, com(b(i), a(i)), com(c(i), d(i)));
  42. productTest(i, com(b(i), a(i)), com(d(i), c(i)));
  43. productTest(i, com(b(i), c(i)), com(d(i), a(i)));
  44. productTest(i, com(b(i), d(i)), com(c(i), a(i)));
  45. productTest(i, com(c(i), a(i)), com(d(i), b(i)));
  46. productTest(i, com(c(i), b(i)), com(d(i), a(i)));
  47. }
  48. System.out.println("总共调用判断的次数为:"+sum);//TMJG添加此行并注释
  49. }
  50. }

方法二:

本方法是对方法一的改进,跳过了一些数字(如1100这样末尾两个0的,如1010、1001这样明显不可能是吸血鬼数字的数字),并且避免了出现重复的可能性,但是效率仍然很低,需要判断104942次。

public class SearchforVampireNumbersLJ {
public static int count = 0;// 记录一共有多少个吸血鬼数字
public static int k=0;//记录调用判断多少次
public static void main(String[] args) {
for (int i = 1001; i < 10000; i++) {
// 如果数字是像1100这种末尾至少有2个0的,则跳过
if (i % 100 == 0) {
continue;
}
// 获得数字四个数值位上的数字,这里我们假定四位数表示为abcd
int a = i / 1000;
int b = (i - a * 1000) / 100;
int c = (i - a * 1000 - b * 100) / 10;
int d = i - a * 1000 - b * 100 - c * 10;
// 判断四个位置上是否有两个0存在的情况,如1010,并跳过这些数,由于千位不可能为0,因此只需要判断另外三位是否有2个0的情况
// 当3个数中有2个0时,必然存在“3个数之和等于其中某一个数”,以此作为判断依据,而后两位为0的也已经排除,其实只需要判断如1001,和1010这种情况即可
if (b + c + d == c || b + c + d == d) {
continue;
}
// 排除掉各种情况后,可以开始真正的吸血鬼数字筛选了
// 那么一共有12种情况:abcd,abdc,acbd,acdb,adbc,adcb,bacd,badc,bcda,bdca,cadb,cbda
if (search(i, a, b, c, d)) {
} else if (search(i, a, b, d, c)) {
} else if (search(i, a, c, b, d)) {
} else if (search(i, a, c, d, b)) {
} else if (search(i, a, d, b, c)) {
} else if (search(i, a, d, c, b)) {
} else if (search(i, b, a, c, d)) {
} else if (search(i, b, a, d, c)) {
} else if (search(i, b, c, d, a)) {
} else if (search(i, b, d, c, a)) {
} else if (search(i, c, a, d, b)) {
} else if (search(i, c, b, d, a)) {
}
}
System.out.println("四位数的吸血鬼数字一共有" + count + "个。");
System.out.println("一共调用判断次数为" + k);
}

//判断是否满足条件
static boolean search(int i, int a, int b, int c, int d) {
k++;
if ((a * 10 + b) * (c * 10 + d) == i) {
searchfor(i,a,b,c,d);//如果满足条件,则打印结果
return true;
}else{
return false;
}
}

//满足条件即打印,并且统计个数
static void searchfor(int i, int a, int b, int c, int d) {
count++;
System.out.println(i + "=" + (a * 10 + b) + "*" + (c * 10 + d));
}
}

方法三:

以下是网上找的代码,该算法采用逆向思维,4位数字的吸血鬼数字只能拆分成两个2位数,因此遍历所有两个两位数相乘的情况,除去不符合的情况不用判断,其他挨个判断即可。

public class SearchforVampireFromInternet {
/**
* 代码来自网络,略作修改并添加了注释
* 该算法只需要执行3721次
*/
public static void main(String[] args) {
String[] targetNum = null;
String[] gunNum=null; //目标数字和枪数字(即对比数字)
int sum = 0; //吸血鬼数字的总个数
int count=0; //有效判断次数,那些乘积不是4位数的就排除了
for (int i = 10; i < 100; i++) {
for (int j = i+1; j < 100; j++) { //没有哪个两位数满足ab*ab=abab(不信可以编程验证),所以这里j从i+1开始就可以了
int i_target = i * j;
if (i_target < 1000 || i_target > 9999)
continue; // 积不是4位数则跳过
count++;
targetNum = String.valueOf(i_target).split(""); //将其转换为一个字符串数组
gunNum = (String.valueOf(i) + String.valueOf(j)).split("");
java.util.Arrays.sort(targetNum); //升序排列,因为只有排列了再比较才能保证不遗漏abcd=ba*dc这样的情况
java.util.Arrays.sort(gunNum);
if (java.util.Arrays.equals(targetNum, gunNum)) {
// 排序后比较,为真则找到一组
sum++;
System.out.println("第" + sum + "个: " + i_target+"="+i + "*" + j);
}
}
}
System.out.println("共进行了"+count+"次判断,找到" + sum + "个吸血鬼数字。");
}
}

时间: 2024-10-04 18:54:05

Thinking In Java 里面吸血鬼数字题的相关文章

【Java】 Thinking in Java 4.8 练习10 吸血鬼数字

题目: 吸血鬼数字是指位数为偶数的数字,可以有一对数字相乘得到,而这对数字各包含成绩的一半位数的数字,其中从最初的数字中选取的数字可以任意排序.  以两个0结尾的数字是不允许的.写一个程序,找出4位数中所有吸血鬼数字. 方法一: 1 public static void main(String[] args) { 2 outer: for (int i = 10; i <= 99; i++) { 3 for (int j = i + 1; j <= 99; j++) { 4 int sum =

《Thinking in Java》习题——吸血鬼数字

最近在看<Java编程思想>,这本书非常棒,不愧是Java程序员的圣经.看到第四章,后面有道题目很有意思,于是就自己做了做. 1. 我的思路很简单,但是算法效率非常之低.就是把4位数拆成4个数字,比如1260--->1,2,6,0.然后4位数字组合成两个2位数,计算它们 的乘积,相等则就是吸血鬼数字. 1 public class Test2 { 2 /* 3 * 将4位数拆分成4个数 4 * */ 5 public int [] array(int num){ 6 int [] a =

Java编程思想——吸血鬼数字问题

吸血鬼数字:我最开始想的是把四位数拆开,然后进行自由组合然后相乘,最后比较得到结果,在网上去看了一些朋友的做法,让我大吃一惊啊,想到自己的算法也要好好看了 ,这样子下去是不行滴 现贴出代码: package edu.cqu.main; import java.util.Arrays; /** * 问题描述: * 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字, * 其中从最初的数字中选取的数字可以任意排序. * 例如: * 1260 = 21 *

Java - 吸血鬼数字

吸血鬼数字是指位数是偶数的数字, 由一对相乘的数字得到, 而且每个数字包含乘积一半位数的数字. 如: 1092: 12*91 1207: 17*71 1250: 25*50 1260: 21*60 1275: 17*75 1278: 18*71 1325: 25*53 找出4位数的所有吸血鬼数字. //: Main.java import java.util.ArrayList; /** * 吸血鬼数字 */ class Main { public static boolean vampire(

Java 找出四位数的全部吸血鬼数字 基础代码实例

/** * 找出四位数的全部吸血鬼数字 * 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序. * 以两个0结尾的数字是不同意的. *   比例如以下列数字都是吸血鬼数字 1260=21*60 1827=21*87 2187=27*81 ... * 比較笨的低效率的做法: 遍历全部四位数, 每生成一个四位数的时候, *         在双重循环遍历两位数,在两位数的内层循环中推断是否与最外层循环的四位数相等

【Java编程思想 - 练习】吸血鬼数字

Thinking in Java 这个程序我自己敲出来的代码,用的方法很笨的感觉,将就着吧,目前没时间想那么多,得继续学啊. 1 class Vnum{ 2 public static void main(String args[]){ 3 CheckVampire cVampire = new CheckVampire(); 4 for(int i=1000;i<10000;i++){ 5 if(cVampire.isVampire(i)){ 6 System.out.println(i);

《java编程思想》读后笔记:二,吸血鬼数字

书本p75中一道读后练习思考题,题目如下: 吸血鬼数字是指位数为偶数的数字,可以有一对数字相乘得到,而这对数字各包含成绩的一半位数的数字,其中从最初的数字中选取的数字可以任意排序.一两个0结尾的数字是不允许的,例如,下列数字都是"吸血鬼数字": 1260=21*60,1827=21*87,2187=27*81 写一个程序,找出4位数的所有吸血鬼数字. 个人代码: public static void main(String[] args) { Map<String,String&

java吸血鬼数字

很惭愧(其实没什么惭愧,水平就这样),搞了半晌才写出来了一个求四位吸血鬼数字的方法 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序. 以两个0结尾的数字是不允许的,例如,下列数字都是"吸血鬼"数字: 1260 = 21 * 60 1827 = 21 * 87 2187 = 27 * 81 int len = 4; // 求出四位值得范围 int max = (int) (Math.pow(10,

【Java】求所有四位吸血鬼数字

1 package com.xt.homework.tools; 2 /** 3 * 4 * 7. 题目 5 * 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘得到, 6 * 而这对数字的位数是原数字的一半位数,并且由组成原数字的各个位数组成, 7 * 以两个0结尾的数字不是吸血鬼数字. 8 * 例如:1260 = 21 * 60 1827 = 21 * 87 2187= 27 * 81 9 * 求所有四位吸血鬼数字 10 * 11 * @author 天耀二期 12 * 杨勃隆 13 */