• Project Euler 92:Square digit chains 平方数字链


    题目

    Square digit chains

    A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.

    For example,

    44 → 32 → 13 → 10 → 1 → 1
    85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

    Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that EVERY starting number will eventually arrive at 1 or 89.

    How many starting numbers below ten million will arrive at 89?


    平方数字链

    将一个数的所有数字的平方相加得到一个新的数,不断重复直到新的数已经出现过为止,这构成了一条数字链。

    例如,

    44 → 32 → 13 → 10 → 1 → 1
    85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

    可见,任何一个到达1或89的数字链都会陷入无尽的循环。更令人惊奇的是,从任意数开始,最终都会到达1或89。

    有多少个小于一千万的数最终会到达89?

    解题

    这个链式的之前好有有个题目和这个差不多的,直接暴力很简单。

    JAVA

    package Level3;
    
    public class PE092{
        static void run(){
            int MAX = 10000000;
            int count = 0;
            for(int num=1;num<=MAX;num++){
                int numx = num;
                if(is89(numx))
                    count +=1;
            }
            System.out.println(count);
        }
    //    8581146
    //    running time=1s973ms
        static boolean is89(int num){
            int next_num = num;
            while(true){
                if(next_num == 89) break;
                if(next_num == 1) break;
                next_num = nextNum(next_num);
            }
            if(next_num ==89)
                return true;
            return false;
        }
        static int nextNum(int num){
            int next_num = 0;
            while(num!=0){
                int tmp = num%10;
                next_num += tmp*tmp;
                num/=10;
            }
            return next_num;
        }
    
        
        public static void main(String[] args) {
            long t0 = System.currentTimeMillis();
            run();
            long t1 = System.currentTimeMillis();
            long t = t1 - t0;
            System.out.println("running time="+t/1000+"s"+t%1000+"ms");
    
        }
    }

     Python运行时间比较长

    # coding=gbk
    
    import time as time 
    from itertools import combinations  
    def run():
        MAX = 10000000
        count = 0
        for num in range(1,MAX):
            if is89(num):
                count+=1
        print count 
     
    # 8581146
    # running time= 305.638000011 s   
    def next_num(num):
        return sum([a*a for a in map(int ,str(num))])
    
    def is89(num):
        while True:
            if num == 89 or num == 1:
                break
            num = next_num(num)
        if num == 89:
            return True 
        return False 
    
    t0 = time.time()
    run() 
    t1 = time.time()
    print "running time=",(t1-t0),"s"
    
                

    85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

    题目给了一个这样的提示,只有我们知道中间的数,就一定能到89

    最大值是9999999 ,nextnum = 9*9*7 = 567 ,可以定义一个568的数组来保存中间的计算结果能到达89的。

    这里我只定义一个boolean数组Judge。先保存前一步的值numx, 若nextnum[numx] == 89 则,则Judge[numx] ==True

    在以后我们可以先判断nextnum在Judge中是否是true,true就不用计算了。

    当然如果定义一个矩阵,保存所有的计算中间值,这个比较复杂啊,对了,可以定义一个set,也很好判断是否存在。下面尝试一下。

    下面run2() 是定义boolean数组的,run3()是定义两个set的。

    定义boolean数组的  对所有的值是否都能判断? 这里就不知道了。所以才想起了定义set的

    package Level3;
    
    import java.util.TreeSet;
    
    public class PE092{
        static void run3(){
            int MAX = 10000000;
            int count =0;
            TreeSet<Integer> path = new TreeSet<Integer>();
            TreeSet<Integer> judge = new TreeSet<Integer>();
            for(int num =2;num<MAX;num++){
                int numx = nextNum(num);
                if(path.contains(numx)){
                    count +=1;
                }else{
                    while(true){
                        judge.add(numx);
                        numx = nextNum(numx);
                        if(path.contains(numx) || numx==89){
                            path.addAll(judge);
                            judge.clear();
                            count +=1;
                            break;
                        }
                        if(numx == 1){
                            judge.clear();
                            break;
                        }
                    }
                }
            }
            System.out.println(count);
        }
    //    8581146
    //    running time=0s953ms
        
        // 9*9*7 = 567 定义一个长度是567的数组保存之前计算过程中的值  
        // 若以89结束定义为true 以后认为是true就可以直接认为是89结束了
        static void run2(){
            int MAX = 10000000;
            int count = 0;
            boolean Judge[] = new boolean[568];
            for(int num =1;num<MAX;num++){
                // 求下一个数
                int numx = nextNum(num);
                // 下一个数是否计算过
                if(Judge[numx]){
                    count+=1;
                }else{ 
                    while(true){
                        // 继续求下一个数 
                        int tmp = nextNum(numx);
                        // 计算过或者 遇到89的时候把之前的数更行Judge[numx]  
                        if(Judge[tmp] || tmp==89){
                            count+=1;
                            Judge[numx] = true;
                            break;
                        }
                        if(tmp ==1) break;
                        numx = tmp;
                        
                    }
                }
            }
            System.out.println(count);
        }
    //    8581146
    //    running time=0s944ms
        static void run(){
            int MAX = 10000000;
            int count = 0;
            for(int num=1;num<=MAX;num++){
                int numx = num;
                if(is89(numx))
                    count +=1;
            }
            System.out.println(count);
        }
    //    8581146
    //    running time=1s973ms
        static boolean is89(int num){
            int next_num = num;
            while(true){
                if(next_num == 89) break;
                if(next_num == 1) break;
                next_num = nextNum(next_num);
            }
            if(next_num ==89)
                return true;
            return false;
        }
        static int nextNum(int num){
            int next_num = 0;
            while(num!=0){
                int tmp = num%10;
                next_num += tmp*tmp;
                num/=10;
            }
            return next_num;
        }
    
        
        public static void main(String[] args) {
            long t0 = System.currentTimeMillis();
            run2();
            long t1 = System.currentTimeMillis();
            long t = t1 - t0;
            System.out.println("running time="+t/1000+"s"+t%1000+"ms");
    
        }
    }

    Python

    # coding=gbk
    
    import time as time 
    def run2():
        MAX = 10000000
        count = 0 
        path=[]
        judge=[]
        for num in range(1,MAX):
            numx = next_num(num)
            if numx in path:
                count +=1
            else:
                while True:
                    judge.append(numx)
                    numx = next_num(numx)
                    if numx in path or numx == 89:
                        count+=1
                        path +=judge
                        judge=[]
                        break
                    if numx ==1:
                        judge = []
                        break
        print count 
    #     8581146
    # running time= 165.453000069 s
  • 相关阅读:
    火眼金睛算法,教你海量短文本场景下去重
    CynosDB技术详解——架构设计
    CynosDB技术详解——存储集群管理
    解决 "Script Error" 的另类思路
    Go 语言实践(一)
    Vue.js的复用组件开发流程
    MYSQL中的COLLATE是什么?
    Blending
    AlphaTesting
    Culling & Depth Testing
  • 原文地址:https://www.cnblogs.com/bbbblog/p/5010427.html
Copyright © 2020-2023  润新知