下一个回文数这个函数写了好久,最后终于通过了,等有时间看看大佬的题解。
回文数的个数明显要少于素数的个数,所以这里采用先判断回文数再判断素数的方法
//判断素数
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;
}
超时了!!!
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];
}