题目:给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。假设环境不允许存储 64 位整数(有符号或无符号)。来源:力扣(LeetCode)
错解:
class Solution {
public:
int reverse(int x) {
vector<int> nums(100);
int n=0;
bool active;
if(x<0){
active=false;
x*=-1;
}//-2147483648去掉符号后为2^31超过范围
//循环的判断条件应该是while(x!=0)去掉判断正负
//尽量减少if语句
else if(x>0)active=true;else return 0;
for(int i=0;x>0;i++,x/=10){
nums[i]=x%10;
n++;
}
int res=0;//c++中long和int都是32位,几乎没差别,而long long为64位
for(int i=1,t=1;i<=n;i++,t*=10){//t有可能溢出
int temp=t*nums[n-i];//temp有可能溢出
if(res+temp>pow(2,31)&&active)return 0;
else if(res+temp>=pow(2,31)&&active)return 0;
res+=temp;
}
if(!active)res*=-1;
return res;
}
};
报错:
runtime error: signed integer overflow: 1000000000 * 9 cannot be represented in type 'int' (solution.cpp) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:28:21
分析:
由于判断之前计算机的数据就已经有可能超过整数范围,故只能在前一位的时候就要判断,即需要判断(2^31)/10(214748364),位数少于10位的数怎么反转都不会溢出,到第九位时和214748364比较相当于一次性比较了前九位,最后还需要比较一下最后一位。2^31最后一位为7,反转后最后一位不能为7,但是题目给出的是整数,所以反转后最后一位最大只能是2,故只需要判断九位即可。
正解:
class Solution {
public:
int reverse(int x) {
vector<int> nums(100);
int n=0;
while(x!=0){
nums[n]=x%10;
x/=10;
n++;
}
long res=0;
for(int i=0;i<n;i++){
if (res>pow(2,31)/10) {
return 0;
}
if (res<pow(2,31)/10*(-1)) {
return 0;
}
res*=10;
res+=nums[i];
}
return res;
}
};
优化:
可以看到两遍遍历多余,一维数组可以压缩成零维数组。
class Solution {
public:
int reverse(int x) {
int nums=0;
int res=0;
while(x!=0){
nums=x%10;
x/=10;
if (res>pow(2,31)/10) {
return 0;
}
if (res<pow(2,31)/10*(-1)) {
return 0;
}
res*=10;
res+=nums;
}
return res;
}
};
总结:
本题考察了对数据类型了解,C++的int为32位、long为32位,long long为64位。同时应注意正数和负数的数据范围不一样,不能改变符号去判断,会让代码变得十分复杂,在编程中注意减少if语句的使用,注意遍历是否需要多次,同时注意数组的维度是否可以压缩。