JAVA_吸血鬼數字 多種方法實現


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM