俄罗斯娃娃Primes

时间:2014-08-10 09:04:27

标签: java primes

在一次采访中询问了这个问题(关于素数) Russian Doll Primes

它们通常被称为Truncatable Primes。 我在wiki上找到了这段代码

public static void main(String[] args){

    final int MAX = 1000000;

    //Sieve of Eratosthenes (using BitSet only for odd numbers)
    BitSet primeList = new BitSet(MAX>>1); 
    primeList.set(0,primeList.size(),true); 

    int sqroot = (int) Math.sqrt(MAX); 
    primeList.clear(0); 
    for(int num = 3; num <= sqroot; num+=2) 
    { 
        if( primeList.get(num >> 1) ) 
        { 
            int inc = num << 1;
            for(int factor = num * num; factor < MAX; factor += inc) 
            { 
                //if( ((factor) & 1) == 1) 
                //{ 
                primeList.clear(factor >> 1); 
                //} 
            } 
        } 
    }


    //Find Largest Truncatable Prime. (so we start from 1000000 - 1
    int rightTrunc = -1, leftTrunc = -1;
    for(int prime = (MAX - 1) | 1; prime >= 3; prime -= 2)
    {
        if(primeList.get(prime>>1))
        {
            //Already found Right Truncatable Prime?
            if(rightTrunc == -1)
            {
                int right = prime;
                while(right > 0 && primeList.get(right >> 1)) right /= 10;
                if(right == 0) rightTrunc = prime;
            }

            //Already found Left Truncatable Prime?
            if(leftTrunc == -1 )
            {
                //Left Truncation
                String left = Integer.toString(prime);
                if(!left.contains("0"))
                {
                    while( left.length() > 0 ){
                        int iLeft = Integer.parseInt(left);
                        if(!primeList.get( iLeft >> 1)) break;
                        left = left.substring(1);
                    }
                    if(left.length() == 0) leftTrunc = prime;
                }
            }
            if(leftTrunc != -1 && rightTrunc != -1) //Found both? then Stop loop
            {
                break;
            }
        }
    }
    System.out.println("Left  Truncatable : " + leftTrunc);
    System.out.println("Right Truncatable : " + rightTrunc);
}

这给出了输出:

Left  Truncatable : 998443
Right Truncatable : 796339

但是我无法解决这个特殊的俄罗斯娃娃素数问题,就像你有一个素数而你删除这个素数的左或右数字然后如果得到的数字是素数还是不是?

我是新手,所以请原谅任何错误。

4 个答案:

答案 0 :(得分:2)

让我们从头开始:

根据您提供的问题所提供的链接:

  

“俄罗斯娃娃大奖赛是   可以重复删除正确数字的素数,并且是   仍然是素数。“

我假设您有一个函数boolean isPrime(int)来查明数字是否为素数。

谷歌搜索,我们将从Wikipedia中发现,截至73,939,133的右截断素数的数量 83 ,这使得蛮力成为可行的选择;但是这里可以采用一些优化技术:

  1. 由于我们右截断,我们可以安全地消除偶数(因为任何偶数都不是素数,所以在它上面生成的任何数字都不会是俄罗斯娃娃素数。)
  2. 由于任何以5开头的数字都可以被5整除,那么根据我在前一点中提到的相同规则,我们可以消除5。
  3. 这给我们留下了包含1,3,7和9的数字。

    现在,如果我们想要生成这4个数字的所有可能组合,这些组合不超过您提到的最大值(1,000,000),则只需要4,096次迭代。

    这种技术的缺点是我们现在有4,096个数字,其中包含可能的非素数,或者由非素数形成的素数,因此不是俄语玩偶素数。我们可以通过循环和检查来消除这些数字;或者更好的是,我们可以更仔细地检查俄罗斯娃娃素数。

    在检查了我从上面的链接中引用的规则后,我们发现俄罗斯玩偶素数是素数,其右数字可以 重复 移除,并且仍然是素数(并因此仍然是俄罗斯娃娃素数,因为 反复 这个词)!

    这意味着我们可以从最小的单位俄罗斯娃娃素数工作,工作我们上面使用的我们这一代魔法,并且由于俄罗斯娃娃素数形成的任何素数是俄罗斯娃娃素数,我们可以消除早期的非素数,导致俄罗斯娃娃素数的清单,同时大大减少了这样一个节目的运行时间。

    看看下面的代码:

    void russianDollPrimesGeneration(int x) {
        x *= 10;
        if (x * 10 >= 1000000) return;
        int j;
        for (int i=1; i<=9; i+=2) {
            if (i == 5) continue;
            j = x + i;
            if (isPrime(j)) {
                addToRussianDollPrimesList(j);
                russianDollPrimesGeneration(j);
            }
        }
    }
    

    前提是void addToRussianDollPrimesList(int x)是一个函数,它将x添加到我们之前保存的列表中以存储俄罗斯玩偶素数。

    更新说明

    请注意,您可以将void russianDollPrimesGeneration(int x)的调用放在void addToRussianDollPrimesList(int x)函数内的if条件中,因为每当我们调用前一个函数时,我们总是会调用后一个函数参数。我在这里将它们分开以强调生成函数的递归性质。

    另请注意,必须使用整数0运行此函数。

    最后要注意的是,有很多情况下上面的生成函数void russianDollPrimesGeneration(int x)都不计算在内,即使它们是俄罗斯娃娃素数。

    请记住,当我们省略2和5时,因为偶数和数字除以5不能是素数,所以不能是俄罗斯娃娃素数?因此不能形成俄罗斯娃娃大奖?那么,那个案子不适用于2和5,因为它们是素数,因为它们是单个数字,因此它们是俄罗斯娃娃素数,并且有资格形成俄罗斯娃娃素数,如果放在左侧,如23和53.

    那么如何纠正我们的代码以包含这些特殊情况?

    我们可以创建一个包装函数来添加这两个数字并检查可以使用它们形成的俄罗斯娃娃素数(这将是我们上面使用的相同的生成函数)。

    void generationWrapperFunction(int x) {
        addToRussianDollPrimesList(2);
        russianDollPrimesGeneration(2);
        addToRussianDollPrimesList(5);
        russianDollPrimesGeneration(5);
        russianDollPrimesGeneration(0);
    }
    

    END UPDATED NOTE

    这个小函数将生成一个俄罗斯娃娃素数列表,然后可以搜索我们正在寻找的号码。

    另一种选择,但我相信会更耗时,是以下递归函数:

    boolean isRussianDollPrime(int n) {
        if (!isPrime(n)) return false;
        if (n < 10) return true;
        return isRussianDollPrime(n / 10);
    }
    

    可以修改此函数以使用左截断素数。但是,基于生成的解决方案对于左截断素数很难实现。

答案 1 :(得分:1)

您的问题是使用此代码还是解决问题?

如果要解决它,你可以使用Sieve算法生成质数,然后检查元素是否为素数(如果它是素数,那么检查元素/ 10是否也是素数)

答案 2 :(得分:1)

让我们从一个简单的假设开始,我们知道如何编写代码来检测值是否为素数。在编码面试中,他们很可能不会期望你退出Eratosthenes&#34; Sieve of Eratosthenes&#34;。您应该从处理x<=1(false)和x==2(true)的特殊情况的简单代码开始。然后检查偶数!(x % 2)(false)。然后从3..sqrt(x)循环i(每次递增+2)以查看是否存在x的奇数除数。

boolean isPrime(long x)
{
   // your code goes here
}

一旦我们有一个函数告诉我们一个值是否为素数,我们就可以轻松地构建函数来检测一个值是否为俄语Prime。因此,我们只需要循环我们的值,每次检查素数,然后切断右侧。从数字中删除最右边数字的最简单方法是将其除以10。

boolean isRussianPrime(long x)
{
    boolean result = isPrime(x);

    while ((x != 0) && result)
    {
       // chop off the right digit of x
       x = x / 10;
       if (x != 0)
       {
           result = isPrime(x);                 
       }
    }

    return result;
}

这就是它的全部内容。

答案 3 :(得分:0)

package com.example.tests;

公共类RussianDollPrimeNumber {

public static void main(String[] args) {

    int x= 373;
    int k;
    int n =x;


    for ( k= String.valueOf(x).length()-1;k>0;k--){
        System.out.println(n);
        if (isPrime(n)){
            String m=String.valueOf(n).substring(0, k);
            n=Integer.parseInt(m);
            continue;

        }else {
            break;
        }
    }

    if( k==0){
        System.out.println("Number is Russianl Doll Number "+x);
    }else {
        System.out.println("Number is not Russianl Doll Number "+x);
    }



}

private static  boolean isPrime(int x) {
    boolean check=true;
    for (int i=2;i<x/2;i++){
        if( (x%i)==0){

        check=false;

        }
    }

    return check;
}

}