目录

裴先生
裴先生
发布于 2020-12-10 / 5 阅读
0
0

Java 实现吸血鬼数字查找算法

原创

问题描述

吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序。以两个0结尾的数字是不允许的。

例如下列数字都是吸血鬼数字:

  • 1260 = 21 × 60
  • 1827 = 21 × 87
  • 2187 = 27 × 81

算法实现

优化版本的吸血鬼数字查找器

package cn.peiluming.vampire;

import java.util.*;

/**
 * 吸血鬼数字查找器
 * 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,
 * 而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序。
 * 
 * @author plm
 */
public class VampireNumberFinder {
    
    /**
     * 查找指定位数的吸血鬼数字
     * @param digitCount 位数(必须为偶数)
     * @return 吸血鬼数字列表
     */
    public static List<VampireResult> findVampireNumbers(int digitCount) {
        if (digitCount % 2 != 0) {
            throw new IllegalArgumentException("位数必须为偶数");
        }
        
        List<VampireResult> results = new ArrayList<>();
        int halfDigit = digitCount / 2;
        int minMultiplier = (int) Math.pow(10, halfDigit - 1);
        int maxMultiplier = (int) Math.pow(10, halfDigit) - 1;
        
        for (int num1 = minMultiplier; num1 <= maxMultiplier; num1++) {
            for (int num2 = num1; num2 <= maxMultiplier; num2++) {
                long product = (long) num1 * num2;
                
                // 检查乘积是否符合位数要求
                if (product < Math.pow(10, digitCount - 1) || product >= Math.pow(10, digitCount)) {
                    continue;
                }
                
                // 排除以两个0结尾的情况
                if (endsWithZeros(num1, num2)) {
                    continue;
                }
                
                // 检查数字是否匹配
                if (isVampireNumber(num1, num2, product)) {
                    results.add(new VampireResult(num1, num2, product));
                }
            }
        }
        
        return results;
    }
    
    /**
     * 检查两个数的乘积是否为吸血鬼数字
     * @param num1 第一个因子
     * @param num2 第二个因子
     * @param product 乘积
     * @return 是否为吸血鬼数字
     */
    private static boolean isVampireNumber(int num1, int num2, long product) {
        String productStr = String.valueOf(product);
        String factorsStr = String.valueOf(num1) + String.valueOf(num2);
        
        char[] productChars = productStr.toCharArray();
        char[] factorsChars = factorsStr.toCharArray();
        
        Arrays.sort(productChars);
        Arrays.sort(factorsChars);
        
        return Arrays.equals(productChars, factorsChars);
    }
    
    /**
     * 检查两个数是否都以0结尾(避免无效情况)
     * @param num1 第一个数
     * @param num2 第二个数
     * @return 是否都以0结尾
     */
    private static boolean endsWithZeros(int num1, int num2) {
        return (num1 % 10 == 0 && num2 % 10 == 0);
    }
    
    /**
     * 吸血鬼数字结果类
     */
    public static class VampireResult {
        private final int factor1;
        private final int factor2;
        private final long product;
        
        public VampireResult(int factor1, int factor2, long product) {
            this.factor1 = factor1;
            this.factor2 = factor2;
            this.product = product;
        }
        
        @Override
        public String toString() {
            return String.format("%d × %d = %d", factor1, factor2, product);
        }
        
        // Getters
        public int getFactor1() { return factor1; }
        public int getFactor2() { return factor2; }
        public long getProduct() { return product; }
    }
    
    public static void main(String[] args) {
        System.out.println("=== 4位吸血鬼数字 ===");
        List<VampireResult> fourDigitVampires = findVampireNumbers(4);
        for (VampireResult result : fourDigitVampires) {
            System.out.println(result);
        }
        System.out.println("总共找到 " + fourDigitVampires.size() + " 个4位吸血鬼数字\n");
        
        System.out.println("=== 6位吸血鬼数字 ===");
        List<VampireResult> sixDigitVampires = findVampireNumbers(6);
        for (VampireResult result : sixDigitVampires) {
            System.out.println(result);
        }
        System.out.println("总共找到 " + sixDigitVampires.size() + " 个6位吸血鬼数字");
    }
}

经典4位吸血鬼数字查找(简化版)

/**
 * 经典4位吸血鬼数字查找器(更简洁的实现)
 */
public class SimpleVampireFinder {
    
    public static void findFourDigitVampireNumbers() {
        int count = 0;
        
        for (int i = 10; i < 100; i++) {
            for (int j = i; j < 100; j++) {
                int product = i * j;
                
                // 检查是否为4位数
                if (product < 1000 || product > 9999) {
                    continue;
                }
                
                // 检查是否以两个0结尾
                if (i % 10 == 0 && j % 10 == 0) {
                    continue;
                }
                
                // 检查数字组成是否相同
                if (hasSameDigits(i, j, product)) {
                    count++;
                    System.out.printf("第%d组: %d × %d = %d%n", count, i, j, product);
                }
            }
        }
        
        System.out.println("共找到 " + count + " 个4位吸血鬼数字");
    }
    
    /**
     * 检查两个因子的数字组合是否与乘积的数字组合相同
     */
    private static boolean hasSameDigits(int num1, int num2, int product) {
        String combined = String.valueOf(num1) + String.valueOf(num2);
        String productStr = String.valueOf(product);
        
        char[] combinedArray = combined.toCharArray();
        char[] productArray = productStr.toCharArray();
        
        Arrays.sort(combinedArray);
        Arrays.sort(productArray);
        
        return Arrays.equals(combinedArray, productArray);
    }
    
    public static void main(String[] args) {
        findFourDigitVampireNumbers();
    }
}

输出示例

=== 4位吸血鬼数字 ===
15 × 93 = 1395
21 × 60 = 1260
21 × 87 = 1827
27 × 81 = 2187
35 × 41 = 1435
45 × 35 = 1575
...
总共找到 X 个4位吸血鬼数字

原创

版权声明:本博客原创文章,由 裴先生 2020年12月10日 发表。
转载说明:除特殊说明外本站文章皆由 CC BY-NC-SA 4.0 协议发布,转载须注明出处。


评论