最近在看《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 = new int [4]; 7 int i=0; 8 while(num!=0){ 9 a[i++]=num%10; 10 num=num/10; 11 } 12 return a; 13 } 14 /* 15 * 將4給數組合成兩個數,相乘與4位數比較。相等就是吸血鬼數字 16 * 17 * */ 18 public boolean equal(int num,int [] a){ 19 for(int i=0;i<4;i++){ 20 for(int j=0;j<4;j++){ 21 if(i==j){ 22 continue; 23 }else{ 24 if(6-i-j==5){//i,j=0或1 25 if((a[i]*10+a[j])*(a[3]*10+a[2])==num||(a[i]+a[j]*10)*(a[3]*10+a[2])==num){ 26 return true; 27 } 28 } 29 else if(6-i-j==4){//i,j=0或2 30 if((a[i]*10+a[j])*(a[3]*10+a[1])==num||(a[i]+a[j]*10)*(a[3]*10+a[1])==num){ 31 return true; 32 } 33 } 34 else if(6-i-j==3&&(i==3||j==3)){ //i,j或0,3 35 if((a[i]*10+a[j])*(a[2]*10+a[1])==num||(a[i]+a[j]*10)*(a[2]*10+a[1])==num){ 36 return true; 37 } 38 } 39 else if(6-i-j==3&&(i==1||j==1)){//i,j=1或2 40 if((a[i]*10+a[j])*(a[3]*10+a[0])==num||(a[i]+a[j]*10)*(a[3]*10+a[0])==num){ 41 return true; 42 } 43 } 44 else if(6-i-j==2){//i,j=1或3 45 if((a[i]*10+a[j])*(a[2]*10+a[0])==num||(a[i]+a[j]*10)*(a[2]*10+a[0])==num){ 46 return true; 47 } 48 } 49 else if(6-i-j==1){//i,j=2或3 50 if((a[i]*10+a[j])*(a[1]*10+a[0])==num||(a[i]+a[j]*10)*(a[1]*10+a[0])==num){ 51 return true; 52 } 53 } 54 } 55 } 56 } 57 return false; 58 } 59 public static void main(String[] args) { 60 Test2 t2 = new Test2(); 61 for(int i =1001;(i<=9999);i++){ 62 if(t2.equal(i, t2.array(i))){ 63 System.out.println(i); 64 } 65 } 66 } 67 68 }
運行結果:
結果是對的,但是算法效率太低。將近要循環9000*4*4=14400次。
在網上找了找,有很多高效的算法。貼出來研究一下別人的思路。
2.
1 public class XiXueGui { 2 /** 3 * 吸血鬼數字算法 4 * 如:12*60=1260 5 * YangL. 6 */ 7 public static void main(String[] args) { 8 String[] ar_str1 = null, ar_str2; 9 int sum = 0; 10 int count=0; 11 for (int i = 10; i < 100; i++) { 12 for (int j = i + 1; j < 100; j++) { 13 int i_val = i * j; 14 if (i_val < 1000 || i_val > 9999) 15 continue; // 積小於1000或大於9999排除,繼續下一輪環 16 count++; 17 ar_str1 = String.valueOf(i_val).split(""); 18 ar_str2 = (String.valueOf(i) + String.valueOf(j)).split(""); 19 java.util.Arrays.sort(ar_str1); 20 java.util.Arrays.sort(ar_str2); 21 if (java.util.Arrays.equals(ar_str1, ar_str2)) { 22 // 排序后比較,為真則找到一組 23 sum++; 24 System.out.println("第" + sum + "組: " + i + "*" + j + "=" 25 + i_val); 26 } 27 } 28 } 29 System.out.println("共找到" + sum + "組吸血鬼數"+"\ncount"+count); 30 31 } 32 }
這個算法非常棒,基本思路是:4位數字的吸血鬼數字只能拆分成兩個2位數。於是就計算兩個2位數相乘(11,12行)。用String.valueOf(j)).split("");的方法來把數字轉換為字符串,排序,比較4位數的字符串和兩個2位數的字符串,若相等,就是吸血鬼數字。把數字的比較,轉換為對字符串的比較,非常棒。
這個算法循環了3721次。
運行結果:
3.《Thinking in Java》官方答案
1 //: control/E10_Vampire.java 2 /****************** Exercise 10 ********************* 3 * A vampire number has an even number of digits and 4 * is formed by multiplying a pair of numbers containing 5 * half the number of digits of the result. The digits 6 * are taken from the original number in any order. 7 * Pairs of trailing zeroes are not allowed. Examples 8 * include: 9 * 1260 = 21 * 60 10 * 1827 = 21 * 87 11 * 2187 = 27 * 81 12 * Write a program that finds all the 4-digit vampire 13 * numbers. (Suggested by Dan Forhan.) 14 ****************************************************/ 15 public class E10_Vampire { 16 public static void main(String[] args) { 17 int[] startDigit = new int[4]; 18 int[] productDigit = new int[4]; 19 for(int num1 = 10; num1 <= 99; num1++) 20 for(int num2 = num1; num2 <= 99; num2++) { 21 // Pete Hartley's theoretical result: 22 // If x·y is a vampire number then 23 // x·y == x+y (mod 9) 24 if((num1 * num2) % 9 != (num1 + num2) % 9) 25 continue; 26 int product = num1 * num2; 27 startDigit[0] = num1 / 10; 28 startDigit[1] = num1 % 10; 29 startDigit[2] = num2 / 10; 30 startDigit[3] = num2 % 10; 31 productDigit[0] = product / 1000; 32 productDigit[1] = (product % 1000) / 100; 33 productDigit[2] = product % 1000 % 100 / 10; 34 productDigit[3] = product % 1000 % 100 % 10; 35 int count = 0; 36 for(int x = 0; x < 4; x++) 37 for(int y = 0; y < 4; y++) { 38 if(productDigit[x] == startDigit[y]) { 39 count++; 40 productDigit[x] = -1; 41 startDigit[y] = -2; 42 if(count == 4) 43 System.out.println(num1 + " * " + num2 44 + " : " + product); 45 } 46 } 47 } 48 } 49 }
運行結果: