题目:
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
解法及思路:
//分析:
//由示例可知:负数和末尾为0(除0外)的数都不是回文数
//那么需要判断正数中,左侧的数是否等于右边
bool isPalindrome(int x){
int len;
int temp = x;
if( x<0 || ((x%10 == 0) && (x!=0)) )
return false;
else if(x == 0)
return true;
else{
//求x的长度len
for(len = 0; temp>0; len++){
temp = temp/10;
}
//printf("len = %d\n",len);//确认长度计算正确
//把x放进数组里
int* n = (int*) malloc(sizeof(int)*len);
temp = x;
for(int i=len-1; i>=0; i--){
n[i] = temp%10;
temp = temp/10;
}
//打印数组,确认数组正确
//for(int a=0;a<len;a++){
// printf("%d",n[a]);
//}
//printf("\n");
//对比
//此处发现代码的重大问题!如果在for中使用continue,虽然不进循环,但是i++和j--仍会执行
int i = 0, j = len-1;
//注意:j是大于等于!!
while(i<len && j>=0){
if(n[i] != n[j]){
return false;
break;
}
else if(n[i] == n[j]){
if(i == len/2){
return true;
break;
}
}
i++;
j--;
}
}
return 0;
}
反思:
在写代码的时候遇到几个问题:
1.做题喜欢按照数学想法,分情况讨论,并且总按第一直接去解题。本来以为只要能解答正确都算过关,但实际上不能这样,在很多现实情况下,需要最优解法,以节省资源。对工作尤其重要,所以后面要继续学习算法。首先要搞清楚时间复杂度的概念。
2.做回文数的题时,第一想法是把数拆分开放进数组里,再去比较数组里前后时候相等。所以首先要获得x的数字长度,再放进数组(因为要给数组确定长度大小,再定义)。
确认数字长度的方法是:用x/10,用len计数,确认x有几位。
然后申请len位的数组大小,把x拆分开放进去:x%10获得末位,再将x/10舍去末位。
3.在写代码时,我刚开始用到了for循环来判断数组中的数:for(i=0,j=len-1;i<len&&j>=0;i++,j--),虽然返回结果是对的,但i和j的数值却和我的预期不一致。后来调试时发现,是因为我在循环中用到了continue。当时我想达成的结果是:在两侧值相等的情况下,就判断i是否已经到了中间,如果到了中间,就证明两侧的数都相同,返回true;否则下标就继续递增/递减。
结果输出结果是对了,但是i和j都一直加到了最边缘的值,并非是我预期的中间值。经查资料,如果在for中使用continue,虽然跳过了后面的语句,但是i++和j--仍会执行。
实际上不需要用continue,让程序顺序执行即可。
同时for里的循环条件,是大范围,不影响计算量(因为for里还有判断条件),同时还可规避一些极端条件,比如len=1时,计算很容易越界。
4.在数组中,用循环判断首位和末位是否相同,如果相同,再往中间靠拢,直到到达中间位。
对于奇数而言,中间位仅一位,可以不用考虑,所以下标判断到len/2即可;
对于偶数而言,中间位有二位,下标判断到len/2-1。
但其实这样区分,只会影响计算量,并不会对输出结果造成影响,所以可以都判断到len/2,无须对代码进行奇数偶数的区分。
5.在写代码时,建议用printf判断变量的值是否符合预期,方便debug