《算法零基础100讲》(第7讲) 素数判定(题解)

866. 回文素数

在这里插入图片描述
在这里插入图片描述
对于这道题,我们可以先将它拆分为两部分,回文和素数。
一. 首先我们先判断回文数,回文数的意思就是一个数的正向和反向的数字是一样的,例如:121,1221,12321等。

  1. 得到一个数的反向我们只需要通过 % 和 / 两个操作符,不断辗转,最后得到。
    在这里插入图片描述
  2. 但是这种将一个整数整个反转的方法有点费时,毕竟我们只需判断,不需要计算。通过分析我们很容易可以看出,每个回文数都有一个对称轴可以将其对半划分,并且两边时一样得,所以我们可以反转后半部分,再与前半部分对比,如果一致则返回true。
    在这里插入图片描述
  3. 但是我们还要考虑当位数为奇数的情况,按照上面的思路,如果时12321,循环结束后,我们会得到,reveredNumber = 123,n = 12,这种情况我们只需判断reveredNumber的前面两位数就行,所以我们的判断条件可以设为 if(reveredNumber == n || reveredNumber % 10 ==n)。

二.我们在考虑第二部分——素数
  素数的定义是只有1和其本身这两个数是他的因子的数为素数。
  判断一个数n是否为素数,我们只需在区间[2, n) 进行计算,如果在这个区间内还有其他的数可以整除n,则返回false。
  但这样的计算量会很大,有没有什么方法能够对其进行优化呢?答案是肯定的。
  我们不妨设x是n的一个因子,那么n / x 为一个整数,且 n / x也是n的一个因子,我们不妨设:

x ≤ n / x
两边同乘x,得:
x ^ 2 ≤ n
得:
x ≤ √n
那么我们只需遍历区间[2, √n]的范围。

代码如下:

bool isPrime(int n) {
    
                  
    int i, sqrtn = sqrt(n + 1e-6);
    if(n <= 1) {
    
    
        return false;                
    }
    for(i = 2; i <= sqrtn; ++i) {
    
    
        if(n % i == 0) {
    
             
            return false;
        }
    }
    return true;                   
}

int primePalindrome(int n){
    
    
    do{
    
    
    	//大于八位的数没有素数,所以直接返回100030001
        if(n >= 10000000)return 100030001;
        int x = n;
        if(x % 10 == 0 && x != 0){
    
    
            continue;
        }
        int reveredNumber = 0;
        //判断是否为回文数
        while(x > reveredNumber){
    
    
            reveredNumber *= 10;
            reveredNumber += x % 10;
            x /= 10;
        }
        bool b = false;
        if(x == reveredNumber || x == reveredNumber / 10){
    
    
            //判断是否为素数
            b = isPrime(n);
        }
        if(b){
    
    
            return n;
        }
    }while(n++);
    return n;
}

剑指 Offer 49. 丑数

在这里插入图片描述
丑数的定义就是只包含质因子2, 3, 5的正整数,并且认为1也是丑数。
要重点注意质因子,没有理解这个概念的话会有点蒙。
这道题我用动态规划思思维来讲解。
分析:

  1. 我们设dp[ i ] 表示第 i 个丑数,那么初始条件便是dp[ 1 ] = 1。
  2. 每个丑数都是由前一个丑数 * 2,*3或 *5得到,所以我们可以定义三个指针p2,p3,p5,分别指向 * 2,*3, *5的三个数。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    以此类推。

代码如下:

int nthUglyNumber(int n){
    
    
    int dp[n + 1];
    dp[1] = 1;
    int p2 = 1, p3 = 1, p5 = 1;
    for(int i = 2; i <= n; i++){
    
    
        int nums2 = dp[p2] * 2;
        int nums3 = dp[p3] * 3;
        int nums5 = dp[p5] * 5;
        dp[i] = fmin(fmin(nums2, nums3), nums5);
        if(nums2 == dp[i]){
    
    
            p2++;
        }
        if(nums3 == dp[i]){
    
    
            p3++;
        }
        if(nums5 == dp[i]){
    
    
            p5++;
        }
    }
    return dp[n];
    
}

猜你喜欢

转载自blog.csdn.net/qq_53060585/article/details/121016159