package test4;

import java.util.Arrays;

/**
* 从TIJ中第4章的练习10看到“吸血鬼数字”,以下几种方法实现以及执行时间对比
* 找出四位数的所有吸血鬼数字
* 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,
* 其中从最初的数字中选取的数字可以任意排序.
* 以两个0结尾的数字是不允许的。
* 例如下列数字都是吸血鬼数字
* 1260=21*60
* 1827=21*87
* 2187=27*81
*/
public class Test1 { public static void main(String[] args) {
long start = System.nanoTime();
fun1();
long end = System.nanoTime();
System.out.println("方法1所用时间:" + (end - start)+"\n"); start = System.nanoTime();
fun2();
end = System.nanoTime();
System.out.println("方法2所用时间:" + (end - start)+"\n"); start = System.nanoTime();
fun3();
end = System.nanoTime();
System.out.println("方法3所用时间:" + (end - start)+"\n"); start = System.nanoTime();
fun4();
end = System.nanoTime();
System.out.println("方法4所用时间:" + (end - start)+"\n");
} private static void fun1() {
//参考答案
int sum = 0;
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("第" + sum + "组: " + num1 + " * " + num2 + " : " + product);
sum++;
}
}
}
}
System.out.println("方法1共找到" + sum + "组吸血鬼数");
} private static void fun2() {
String[] ar_str1, ar_str2;
int sum = 0;
int from;
int to;
int i_val;
for (int i = 10; i < 100; i++) {
from = Math.max(1000 / i, i + 1);
to = Math.min(10000 / i, 100);
// 2个数的乘积是4位数(大于等于1000,小于10000),i确定时,另一个数范围随之确定
for (int j = from; j < to; j++) {
i_val = i * j;
if (i_val % 100 == 0 || (i_val - i - j) % 9 != 0) {
// (i_val - i - j) % 9 != 0 的理解:
// 假设val = 1000a + 100b + 10c + d, 因为满足val = x * y, 则有x =
// 10a + b, y = 10c + d
// 可得val - x - y = 990a + 99b + 9c = 9 * (110a + 11b + c),
// 所以val - x - y能被9整除。
// 满足该条件的数字必定能被9整除,可以直接过滤其他数字。
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("方法2共找到" + sum + "组吸血鬼数");
} private static void fun3() {
int sum = 0;
for (int i = 11; i < 100; i++) {
for (int j = i; j < 100; j++) {
int k = i * j;
// 有另一种变为字符串来操作,比较发现下面的这种方法耗时更少
int[] a = { k / 1000, k / 100 % 10, k / 10 % 100 % 10, k % 1000 % 100 % 10 };
int[] b = { i % 10, i / 10, j % 10, j / 10 };
Arrays.sort(a);
Arrays.sort(b);
if (Arrays.equals(a, b)) {
sum++;
System.out.println("第" + sum + "组: " + i + " * " + j + " = " + k);
}
}
}
System.out.println("方法3共找到" + sum + "组吸血鬼数");
} private static void fun4() {
//逆向思维
String[] targetNum = null;
String[] gunNum = null;
int sum = 0;
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位数则跳过
targetNum = String.valueOf(i_target).split("");
gunNum = (String.valueOf(i) + String.valueOf(j)).split("");
Arrays.sort(targetNum);
Arrays.sort(gunNum);
if (Arrays.equals(targetNum, gunNum)) {
sum++;
System.out.println("第" + sum + "组: " + i_target + "=" + i + "*" + j);
}
}
}
System.out.println("方法4找到" + sum + "个吸血鬼数字。");
}
}

执行结果:

第0组: 15 * 93 : 1395
第1组: 21 * 60 : 1260
第2组: 21 * 87 : 1827
第3组: 27 * 81 : 2187
第4组: 30 * 51 : 1530
第5组: 35 * 41 : 1435
第6组: 80 * 86 : 6880
方法1共找到7组吸血鬼数
方法1所用时间:4880538
第1组: 15*93=1395
第2组: 21*60=1260
第3组: 21*87=1827
第4组: 27*81=2187
第5组: 30*51=1530
第6组: 35*41=1435
第7组: 80*86=6880
方法2共找到7组吸血鬼数
方法2所用时间:43971275 第1组: 15 * 93 = 1395
第2组: 21 * 60 = 1260
第3组: 21 * 87 = 1827
第4组: 27 * 81 = 2187
第5组: 30 * 51 = 1530
第6组: 35 * 41 = 1435
第7组: 80 * 86 = 6880
方法3共找到7组吸血鬼数
方法3所用时间:19352070 第1组: 1395=15*93
第2组: 1260=21*60
第3组: 1827=21*87
第4组: 2187=27*81
第5组: 1530=30*51
第6组: 1435=35*41
第7组: 6880=80*86
方法4找到7个吸血鬼数字。
方法4所用时间:125098134

JAVA_吸血鬼数字 多种方法实现的更多相关文章

  1. Java 吸血鬼数字

    非常羞愧(事实上没什么羞愧.水平就这样).搞了半晌才写出来了一个Java 版求四位吸血鬼数字的方法 吸血鬼数字是指位数为偶数的数字.能够由一对数字相乘而得到.而这对数字各包括乘积的一半位数的数字,当中 ...

  2. str.format() 格式化数字的多种方法

    Python2.6 开始,新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能. 基本语法是通过 {} 和 : 来代替以前的 % . format 函数可以接受不限个参数 ...

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

    /**  * 找出四位数的全部吸血鬼数字  * 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序.  * 以两个 ...

  4. Java 找出四位数的所有吸血鬼数字 基础代码实例

    /**  * 找出四位数的所有吸血鬼数字  * 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序.  * 以两个 ...

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

    最近在看<Java编程思想>,这本书非常棒,不愧是Java程序员的圣经.看到第四章,后面有道题目很有意思,于是就自己做了做.

  6. 无线加密的多种方法及其区别(WEP WPA TKIP EAP)

    无线加密的多种方法及其区别(WEP WPA TKIP EAP) 无线网络的安全性由认证和加密来保证. 认证允许只有被许可的用户才能连接到无线网络: 加密的目的是提供数据的保密性和完整性(数据在传输过程 ...

  7. javascript实现保留两位小数的多种方法

    第一种方法:javascript实现保留两位小数一位自动补零代码实例:第一种方法介绍一下如何实现对数字保留两位小数效果,如果数字的原本小数位数不到两位,那么缺少的就自动补零,这个也是为了统一的效果,先 ...

  8. CSS导航菜单水平居中的多种方法

    CSS导航菜单水平居中的多种方法 在网页设计中,水平导航菜单使用是十分广泛的,在CSS样式中,我们一般会用Float元素或是「display:inline-block」来解决.而今天主要讲解如何让未知 ...

  9. 用 Python 排序数据的多种方法

    用 Python 排序数据的多种方法 目录 [Python HOWTOs系列]排序 Python 列表有内置就地排序的方法 list.sort(),此外还有一个内置的 sorted() 函数将一个可迭 ...

随机推荐

  1. MongoDB 数据自动同步到 ElasticSearch

    我们产品中需要全文检索的功能,后端数据存储主要使用了 MySQL + MongoDB,而其中需要检索的内容是在 MongoDB 中的. MongoDB 本身是自带文本索引功能的,但是,不支持中文.术业 ...

  2. mongodb 3.0下载安装、配置及mongodb最新特性、基本命令教程详细介绍

    mongoDB简介(本文由www.169it.com搜集整理) MongoDB是一个高性能,开源,无模式的文档型数据库,是目前在IT行业非常流行的一种非关系型数据库(NoSql).它在许多场景下可用于 ...

  3. apache2 的https配置和代理https后端nodejs配置

    先进入  /usr/local/apache2/conf  目录 修改 vim httpd.conf  把下面的去掉注释 LoadModule proxy_module modules/mod_pro ...

  4. SQLServer 的存储过程与java交互

    一.   存储过程简介 Sql Server的存储过程是一个被命名的存储在服务器上的Transacation-Sql语句集合,是封装重复性工作的一种方法,它支持用户声明的变量.条件执行和其他强大的编程 ...

  5. time 模块学习

    前情提要: time模块是经常使用的模块.主要是用来记录时间,以及时间上的相关操作 一:时间戳 1:第一种形式 import time print(time.time()) 从1970 1 1 0:0 ...

  6. Eclipse中的创建maven项目,无法添加src/main/java等source folder

    maven无法添加src/main/java 通过Eclipse创建Java Web项目,目录结构如下: 默认是只有src/main/resources 这个source folder 按照maven ...

  7. [HNOI2019]鱼

    Luogu5286 \(2019.4.14\),新生第一题,改了\(3\)个小时 题解-租酥雨,和出题人给的正解一模一样 枚举\(AD\),分别考虑鱼身\(BC\)和鱼尾\(EF\) 到\(E\),\ ...

  8. 认识HTML5中的新标签与新属性

    前端之HTML5,CSS3(一) HTML5中常用内容标签 header标签 header标签定义文档的页眉,基本语法:<header>content</header>. na ...

  9. php实现函数可变参数列表

    使用func_get_args().func_num_args().func_get_arg() 可以构造一个可变参数列表的函数. 首先大致介绍以上三个函数. (1)array func_get_ar ...

  10. FocusBI: SSIS 开发案例(原创)

    关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. <商业智能教程>pdf下载地址 链接:https://pan.baidu.com/ ...