java实现吸血鬼数字的三个想法(附官方答案)
来源:互联网 发布:windows最新版本是什么 编辑:程序博客网 时间:2024/05/29 11:59
自己写了一种方法,优化过后还可以,不过取巧。网上找了两种方法,从运行时间上来看比自己的方法慢
官方的一种方法,运行时间简直快到不可思议,真没法了。
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++) { 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;} } } }
- java实现吸血鬼数字的三个想法(附官方答案)
- 吸血鬼数字的实现(thinking in java练习题)
- 4位吸血鬼数字的java实现
- 吸血鬼数字(java)
- 吸血鬼数字(JAVA)
- 吸血鬼数字--Java实现探究
- [Java实现]吸血鬼数字问题的坑和尝试
- THINKING IN JAVA中吸血鬼数字题目的答案,稍作修改
- 吸血鬼数字检验之java实现
- 找出四位数的所有吸血鬼数字(JAVA)
- 最简单的吸血鬼数字实现方法
- 吸血鬼数(Java实现)
- JAVA 吸血鬼数字学习
- Java - 吸血鬼数字
- java 吸血鬼数字
- Java 吸血鬼数字
- 吸血鬼数字java算法
- 【java】吸血鬼数字
- 真正的匿名者,TOR 的原理
- CAS 实现单点登录oos(3) 自定义登录页面
- action名称一致的BroadcastReceiver 的优先级
- LIGHT OJ 1225 - Palindromic Numbers (II)【回文数】
- 1011 A+B和C
- java实现吸血鬼数字的三个想法(附官方答案)
- 正则表达式--Java
- java笔记--day09--final关键字
- 系统调用、POSIX、C库、系统命令和内核函数
- java异常处理
- Restore IP Addresses
- linux基础教程:文件系统和磁盘
- 大部分人都会做错的经典JS闭包面试题
- VP无限轮播