如何使此代码更有效? Java算法

时间:2016-08-07 21:49:42

标签: java regex algorithm performance coding-efficiency

我正在尝试下面的挑战。 https://www.hackerrank.com/contests/projecteuler/challenges/euler145/submissions/code/25262675

基本上,代码需要从大约1到19位的数字反转一些变化的长度,将这些数字加在一起然后检查结果是否完全由奇数组成,不允许前导0(例如100应该是除外)。

我已经改进的代码可以计算这些数字,但在网站上有一个超时,我觉得它在性能方面不够好。

我尝试过使用正则表达式,但无法正确排序,这会影响结果。任何指导作为写入此内容的最佳方式,以便尽可能快地运行将非常有用,无论是需要使用正则表达式还是其他任何内容。

public static void main(String[] args) {

    Scanner scan = new Scanner(System.in);
    long t = scan.nextInt(); //Number of numbers to test
    for (int i = 1; i <= t; i++){
        long n = scan.nextLong();
        calc(n); //begins calculation
    }
}

public static void calc(long n)
{
    long reversible = 0; //Counter
    for (long i = 1; i < n; i++)
    {
        if (i%10 != 0) //Makes sure number does not end with a zero
        {
            long reverse = 0;
            long j = i;
            long checkOdd;
            //Reverse the number
            while( j != 0 )
            {
                reverse = reverse * 10;
                reverse = reverse + j%10;
                j = j/10; //
            }
            long result = i + reverse; //Add current number and reverse
            while (result != 0)
            {
                //Check and remove numbers to see if odd or not
                checkOdd = result%10;
                if (checkOdd%2 == 0){ //Even detected, move to next number
                    result = 0;                        
                } 
                result = result/10; //Move to next digit
                //Counts and ensures we do not count the same number multiple times
                if (checkOdd%2 == 1 && result == 0) 
                {
                    reversible = reversible + 1;
                }
            }

            /** REGEX TEST CODE -- fails when result is 5 digits long after testing */
            /** if(Pattern.matches("\\d[^02468]", Long.toString(result)))
            {
                System.out.println(result);
                reversible = reversible + 1;
            }*/


        }
    }
    System.out.println(reversible);
}

1 个答案:

答案 0 :(得分:0)

这不能完全解决您的问题,但希望能让您开始思考这个问题。

由于这是关于计算集合的基数,我们应该考虑如何构造该集合的元素,而不是如何检查元素是否在该集合中。

首先,尝试考虑构建特定长度的数字的方法。

我们将以一位数字开头。我们将这些表示为a。如果我们采用a并将其反转,我们会获得a。当这个加倍时,我们得到2a,这总是偶数,因此总是以偶数结束,因此没有。

接下来,1位数字。代表ab,其中ab是数字。反面是ba,最右边的位置(我将从这里开始编号,从0开始,未来参考)总和为(a+b)%10,所以最后一位数只是奇数恰好其中一个和b是奇数。此外,a+b有一个10,我们称之为z。这对下一部分很重要。位数1的总和为(a+b+z)%10。已经确定a+b必须是奇数,z现在必须为0以保持奇数。所以a+b < 10。现在你只需要这个有效的组合数和b数。请注意,两者都不能为0,因为它们位于数字的末尾。

 a | b 
 1 | 2,4,6,8
 2 | 1,3,5,7
  ... 

当然,我们真的需要能够统计这些。因此对a=1我们只需知道b是偶数和b<9所以有4种可能性。对于a=2b为奇数且b<8,因此有4个选项。

你应该能够为3位数字重现这个想法,并希望通过计算可能性数量而不产生或验证任何可能性的节省应该变得更加明显。

编辑:顺便说一句,如果没有为三位数abc努力到达那里,我得出的结论是:

a+c is odd
a+c>=10
b<=4

符合这些规则的任何组合都应该有效。这应该为20提供a,c5b20 * 5 = 100个独立值,因此internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext> { public Configuration() { AutomaticMigrationsEnabled = true; ContextKey = "Fully.Qualified.Namespace.MyDbContext"; } } 总共有3位数字。希望我错了,或者当你尝试时得出同样的结论。

当你进一步扩展时,你应该注意到一些模式允许你推广到任何长度(我认为在长度和长度工作之间可能存在一些重要区别。)

实际上为你提供的解决方案效率不高(而且我确定它们已经存在于某个地方),但希望这可以改变你对如何解决问题的看法,以便你可以解决它。