`
universsky
  • 浏览: 92232 次
文章分类
社区版块
存档分类
最新评论

JAVA算法求水仙花数

 
阅读更多
import java.math.BigInteger;
import java.util.Hashtable;

public class Main {

    private static final int SIZE = 21;
    private int[] countArray = new int[10]; // 个数列表
    private int[] countSumArray = new int[10]; // 个数总数
    private BigInteger[] sumArray = new BigInteger[10];// 值总数
    private int offset = 0;// 浮标

    /**
     * 设置当前浮标对应的个数,个数的总数,值总数
     *
     * @param num
     *            个数
     */
    private void setValue(int num) {
        countArray[offset] = num;
        if (offset == 0) {
            countSumArray[offset] = num;
            sumArray[offset] = p(9 - offset).multiply(n(num));
        } else {
            countSumArray[offset] = countSumArray[offset - 1] + num;
            sumArray[offset] = sumArray[offset - 1].add(p(9 - offset).multiply(n(num)));
        }
    }

    /**
     * 检验当前数据是否匹配
     *
     * @return
     */
    private boolean checkPersentArray() {
        BigInteger minVal = sumArray[offset];// 当前已存在值
        BigInteger maxVal = sumArray[offset].add(p(9 - offset).multiply(n(SIZE - countSumArray[offset])));// 当前已存在值+可能存在的最大值
        // 最小值匹配
        if (minVal.compareTo(MAX) > 0) {
            return false;
        }
        // 最大值匹配
        if (maxVal.compareTo(MIN) < 0) {
            return false;
        }
        String minStr = minVal.compareTo(MIN) > 0 ? minVal.toString() : MIN.toString();
        String maxStr = maxVal.compareTo(MAX) < 0 ? maxVal.toString() : MAX.toString();
        // 找到最小值与最大值间首部相同的部分
        int[] sameCountArray = new int[10];
        for (int i = 0; i < SIZE; i++) {
            char c;
            if ((c = minStr.charAt(i)) == maxStr.charAt(i)) {
                sameCountArray[c - '0'] = sameCountArray[c - '0'] + 1;
            } else {
                break;
            }
        }
        // 判断如果相同部分有数据大于现在已记录的位数,返回false
        for (int i = 0; i <= offset; i++) {
            if (countArray[i] < sameCountArray[9 - i]) {
                return false;
            }
        }
        // 如果当前值的总数为SIZE位,那么判断该值是不是需要查找的值
        if (countSumArray[offset] == SIZE) {
            String sumStr = sumArray[offset].toString();
            BigInteger sum = ZERO;
            for (int i = 0; i < sumStr.length(); i++) {
                sum = sum.add(p(sumStr.charAt(i) - '0'));
            }
            return sum.compareTo(sumArray[offset]) == 0;
        }
        return true;
    }

    /**
     * 退出循环,打印
     *
     * @return
     */
    private void success() {
        System.out.println("find a match number:" + sumArray[offset]);
    }

    /**
     * 将浮标指向下一位数
     *
     * @return
     */
    private void next() {
        offset++;
        setValue(SIZE - countSumArray[offset - 1]);
    }

    /**
     *
     * 回退浮标,找到最近的浮标,并减一
     *
     * @return
     */
    private boolean back() {
        // 回退浮标,找到最近的浮标,并减一
        if (countArray[offset] == 0) {
            while (countArray[offset] == 0) {
                if (offset > 0) {
                    offset--;
                } else {
                    return true;
                }
            }
        }
        if (offset > 0) {
            setValue(countArray[offset] - 1);
            return false;
        } else {
            return true;
        }
    }

    /**
     * 测试程序
     *
     * @param startValue
     *            测试匹配数中包含9的个数
     * @param startTime
     *            程序启动时间
     */
    private void test(int startValue, long startTime) {
        // 设置9的个数
        offset = 0;
        setValue(startValue);
        while (true) {
            if (checkPersentArray()) {// 检查当前提交数据是否匹配
                // 匹配且总数正好为SIZE的位数,那么就是求解的值
                if (countSumArray[offset] == SIZE) {
                    success();
                }
                // 总数不为SIZE,且当前值不在第10位(即不等于0)
                if (offset != 9) {
                    next();
                    continue;
                }
                // 总数不为SIZE,且当前值在第10位。
                if (back()) {
                    break;
                }
            } else {
                if (back()) {
                    break;
                }
            }
        }

        System.out.println(Thread.currentThread() + " End,Spend time " + (System.currentTimeMillis() - startTime) / 1000 + "s");
    }

    /**
     * 主函数
     */
    public static void main(String[] args) {
        final long startTime = System.currentTimeMillis();
        int s = SIZE > 9 ? 9 : SIZE;
        for (int i = 0; i <= s; i++) {
//            new Main().test(i, startTime);
            // 启动十个线程同时运算
            final int startValue = i;
            new Thread(new Runnable() {

                public void run() {
                    new Main().test(startValue, startTime);
                }
            }).start();
        }
    }
    private static final BigInteger ZERO = new BigInteger("0");
    private static final BigInteger MIN;
    private static final BigInteger MAX;

    /**
     * 0-SIZE间的BigInteger
     */
    private static final BigInteger n(int i) {
        return (BigInteger) ht.get("n_" + i);
    }

    /**
     * 0-9的次方的BigInteger
     */
    private static final BigInteger p(int i) {
        return (BigInteger) ht.get("p_" + i);
    }
    /**
     * 用于缓存BigInteger数据,并初始化0-SIZE间的BigInteger和0-9的次方的BigInteger
     */
    private static Hashtable<String, Object> ht = new Hashtable<String, Object>();

    static {
        int s = SIZE < 10 ? 10 : SIZE;
        for (int i = 0; i <= s; i++) {
            ht.put("n_" + i, new BigInteger(String.valueOf(i)));
        }
        for (int i = 0; i <= 10; i++) {
            ht.put("p_" + i, new BigInteger(String.valueOf(i)).pow(SIZE));
        }
        MIN = n(10).pow(SIZE - 1);
        MAX = n(10).pow(SIZE).subtract(n(1));
    }
} 

分享到:
评论

相关推荐

    水仙花数Java程序实现

    System.out.println("水仙花数为:"); for(int i=100;i;i++){ a=i/100; b=i%100/10; c=i%100%10; if(a*a*a+b*b*b+c*c*c==i) System.out.println(i+""); } } }语言实现水仙花数。

    java水仙花数算法

    java水仙花数的计算,新手学习,老鸟绕道

    七种方法求水仙花数

    水仙花数 分别有openMP Java MFC等七种方法

    java小算法 逢七过 水仙花数 逆序数值.md

    有关于逢七过 水仙花数 逆序数值的算法详解以及用Java所编写的代码

    Java求10到100000之间的水仙花数算法示例

    主要介绍了Java求10到100000之间的水仙花数算法,结合实例形式分析了水仙花数的概念及相应的java算法实现技巧,需要的朋友可以参考下

    java笔试算法题40道

    兔子繁殖 半段质数 水仙花数 最大公约数 最小公倍数 数字排序等经典的编程问题

    理解水仙花数.docx

    水仙花数

    10个简单的java算法

    2.水仙花数。3.正整数分解质因数。4.求100-200之间的素数(只能被1和自身整除),并输出。5.非波拉契数列问题。6.sum=a+aa+aaa+aaaa+...7.给一个不多于5位的正整数,求是几位数,并逆序打印各个数字8.排序9.杨辉三角10...

    40个java算法题,都弄会了,java基础就算入门了,很经典

    【程序2】 题目:打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个 "水仙花数 ",因为153=1的三次方+5的三次方+3的三次方。 1.程序分析:利用for循环...

    Java算法20例

    Java常用算法20例,写了个代理类计算方法执行的时间来查看效率 方法描述:兔子生兔子问题 插入排序,快速排序 杨辉三角形 循环移动数组 4个计算题 2个排列 素数,水仙花数,回文数 因子,分解质因数,完数 最大公约数和最小...

    JAVA经典问题算法大全

    其中好汉很多经典的算法,如水仙花数、生兔子、分解质因数等!

    C/C++常用算法手册.秦姣华(有详细书签).rar

    9.4.2 计算水仙花数算法 281 9.5 自守数 283 9.5.1 自守数概述 283 9.5.2 计算自守数算法 284 9.6 最大公约数 287 9.6.1 计算最大公约数算法——搌转相除法 287 9.6.2 计算最大公约数算法一一Stein算法 288 ...

    Java开发技术大全(500个源代码).

    daffodilNumber.java 求水仙花数 division.java 演示整除结果 errorCompoundVariable.java 错误使用局部变量示例 factorial.java 求阶乘 Fibonacci.java 求Fiblnacci数列 GcdAndGcm.java 求最大公约数和最小公...

    Java趣味编程100例 清华大学出版社.zip

    3.2 水仙花数 71 3.3 完全数 74 3.4 相亲数 76 3.5 黑洞数 78 3.6 勾股数 81 3.7 自守数 84 3.8 3位反序数 86 3.9 小结 87 第4章 趣味素数( 教学视频:61分钟) 88 4.1 素数 88 4.2 孪生素数 91 4.3 ...

    java自学之道

    2.3 水仙花数 2.4 分解质因数 2.5 杨辉三角 2.6 学习成绩查询 2.7 求最大公约数与最小公倍数 2.8 完全平方数 2.9 统计字母、空格、数字和其它字符个数 2.10 求主对角线之和 2.11 完数求解 2.12 求s=a+aa+aaa+aaaa+aa...

    国信蓝桥试题算法

    当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。 当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。 当N=5时...

    达内 coreJava 习题答案

    6、输出所有的水仙花数,把谓水仙花数是指一个数3位数,其各各位数字立方和等于其本身, 例如: 153 = 1*1*1 + 3*3*3 + 5*5*5 class DafodilNumber{ public static void main(String[] args){ System.out....

    Java开发技术大全 电子版

    2.7.5求水仙花数92 2.7.6输出图形93 2.7.7输出九九口诀表94 2.8本章小结95 第2篇Java面向对象编程 第3章对象和类98 3.1面向对象的基本概念98 3.1.1对象98 3.1.2类99 3.1.3消息101 3.1.4面向对象的4个基本...

Global site tag (gtag.js) - Google Analytics