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

866. 回文素数

下一个回文数这个函数写了好久,最后终于通过了,等有时间看看大佬的题解。

回文数的个数明显要少于素数的个数,所以这里采用先判断回文数再判断素数的方法

//判断素数
int isPrime(int n) {              
    int i, sqrtn = sqrt(n + 1e-6);
    if(n <= 1) {
        return 0;                 
    }
    for(i = 2; i <= sqrtn; ++i) {
        if(n % i == 0) {          
            return 0;
        }
    }
    return 1;                     
}
//取长度
int len(int n){
    int a=0;
    if(n==0) return 1;
    while(n){
        n/=10;
        a++;
    }
    return a;
}
//判断回文
int ishuiwen(int n){  //把输入按位存到一个数组中,然后通过数组下标进行比较
    int length=len(n);
    int A[length];
    if(length==1) return 1;
    if(n%10==0) return 0;
    for(int i=0;i<length;++i){  //这里写的是低位在前,因为是回文,正反都一样
        A[i]=n%10;
        n/=10;
    }
    for(int i=0;i<length/2;++i){
        if(A[i]!=A[length-1-i]) return 0;
    }
    return 1;
}
//下一个回文数
int next(int n){  //这个函数的思想是找到回文数对称的前半部分,使其+1后再将它补成回文数
    int sum=0;    //要返回的下一个回文数的值
    int k=len(n); //K为回文数的位数
    if(n<9) return ++n;
    else if(n==9) return 11; //排除只有一位的情况
    int length=k/2;          //这个length是原回文数后半部分剩下的位数
    int shun=0,ni=0;         //shun表示前半部分,ni表示后半部分
    shun=n/(pow(10,length)); //找到回文数对称的前半部分
    if(len(shun)!=len(shun+1)) k++;  //当shun=99,999,9999等等时会出现进位情况
    shun++;       //下一个回文数的前半部分
    int a=shun;    
    int flag1=1,flag2=0;     //flag1表示逆序过程中缺失的位数,flag2用来判断会不会缺位
    while(a){
        if(flag2==0&&a%10==0) flag1*=10;
        if(a%10!=0) flag2=1;
        if(shun==flag1&&k%2==0) flag1/=100;  //单独考虑进位情况
        ni=ni*10+a%10;       //逆序
        a/=10;
    }
    if(k%2==1){   //奇数位回文数要丢掉最中间相同的一位
        shun/=10;
    }
    sum=shun*pow(10,len(ni))*flag1+ni;
    return sum;
}


int primePalindrome(int n){
    while(!ishuiwen(n)){
        n++;
    }
    while(!isPrime(n)){
        n=next(n);
    }
    return n;
}

剑指 Offer 49. 丑数

超时了!!! 

int nthUglyNumber(int n){
    if(n==1) return 1;
    int a=2;
    while(n-1){
        int b=a;
        while(b%2==0) b/=2;
        while(b%3==0) b/=3;
        while(b%5==0) b/=5;
        if(b==1) n--;
        a++;
    }
    return a-1;
}

看了leetcode里的题解,原来这就是动态规划呀,其实就是把丑数从小到大依次排序。确实在时间上明显比上面的做法要少很多,减少了很多不必要的判断。

int res=0;

//取三个数中的最小值
int min(int a,int b,int c){   
    if(a<=b&&a<=c){
        res=0;
        return a;
    }
    if(b<=a&&b<=c){
        res=1;
        return b;
    }
    if(c<=a&&c<=b){
        res=2;
        return c;
    }
    return 0;
}
int nthUglyNumber(int n){
    int N[n];
    N[0]=1;
    int a=0,b=0,c=0;
    for(int i=1;i<n;++i){
        N[i]=min(N[a]*2,N[b]*3,N[c]*5);
        if(N[i]==N[i-1]) i--;
        if(res==0) a++;
        else if(res==1) b++;
        else c++;
    }
    return N[n-1];
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值